Header And Logo

PostgreSQL
| The world's most advanced open source database.

Defines | Functions

px-crypt.h File Reference

This graph shows which files directly or indirectly include this file:

Go to the source code of this file.

Defines

#define PX_MAX_CRYPT   128
#define PX_MAX_SALT_LEN   128
#define PX_XDES_ROUNDS   (29 * 25)
#define PX_BF_ROUNDS   6

Functions

char * px_crypt (const char *psw, const char *salt, char *buf, unsigned buflen)
int px_gen_salt (const char *salt_type, char *dst, int rounds)
char * _crypt_gensalt_traditional_rn (unsigned long count, const char *input, int size, char *output, int output_size)
char * _crypt_gensalt_extended_rn (unsigned long count, const char *input, int size, char *output, int output_size)
char * _crypt_gensalt_md5_rn (unsigned long count, const char *input, int size, char *output, int output_size)
char * _crypt_gensalt_blowfish_rn (unsigned long count, const char *input, int size, char *output, int output_size)
char * _crypt_blowfish_rn (const char *key, const char *setting, char *output, int size)
char * px_crypt_des (const char *key, const char *setting)
char * px_crypt_md5 (const char *pw, const char *salt, char *dst, unsigned dstlen)

Define Documentation

#define PX_BF_ROUNDS   6

Definition at line 46 of file px-crypt.h.

#define PX_MAX_CRYPT   128

Definition at line 36 of file px-crypt.h.

Referenced by pg_crypt().

#define PX_MAX_SALT_LEN   128

Definition at line 39 of file px-crypt.h.

Referenced by pg_gen_salt(), pg_gen_salt_rounds(), and px_gen_salt().

#define PX_XDES_ROUNDS   (29 * 25)

Definition at line 43 of file px-crypt.h.


Function Documentation

char* _crypt_blowfish_rn ( const char *  key,
const char *  setting,
char *  output,
int  size 
)

Definition at line 578 of file crypt-blowfish.c.

References BF_atoi64, BF_body, BF_decode(), BF_encode(), BF_itoa64, BF_magic_w, BF_N, BF_set_key(), BF_swap(), i, and BF_ctx::S.

Referenced by run_crypt_bf().

{
    struct
    {
        BF_ctx      ctx;
        BF_key      expanded_key;
        union
        {
            BF_word     salt[4];
            BF_word     output[6];
        }           binary;
    }           data;
    BF_word     L,
                R;
    BF_word     tmp1,
                tmp2,
                tmp3,
                tmp4;
    BF_word    *ptr;
    BF_word     count;
    int         i;

    if (size < 7 + 22 + 31 + 1)
        return NULL;

    if (setting[0] != '$' ||
        setting[1] != '2' ||
        (setting[2] != 'a' && setting[2] != 'x') ||
        setting[3] != '$' ||
        setting[4] < '0' || setting[4] > '3' ||
        setting[5] < '0' || setting[5] > '9' ||
        (setting[4] == '3' && setting[5] > '1') ||
        setting[6] != '$')
    {
        return NULL;
    }

    count = (BF_word) 1 << ((setting[4] - '0') * 10 + (setting[5] - '0'));
    if (count < 16 || BF_decode(data.binary.salt, &setting[7], 16))
    {
        memset(data.binary.salt, 0, sizeof(data.binary.salt));
        return NULL;
    }
    BF_swap(data.binary.salt, 4);

    BF_set_key(key, data.expanded_key, data.ctx.P, setting[2] == 'x');

    memcpy(data.ctx.S, BF_init_state.S, sizeof(data.ctx.S));

    L = R = 0;
    for (i = 0; i < BF_N + 2; i += 2)
    {
        L ^= data.binary.salt[i & 2];
        R ^= data.binary.salt[(i & 2) + 1];
        BF_ENCRYPT;
        data.ctx.P[i] = L;
        data.ctx.P[i + 1] = R;
    }

    ptr = data.ctx.S[0];
    do
    {
        ptr += 4;
        L ^= data.binary.salt[(BF_N + 2) & 3];
        R ^= data.binary.salt[(BF_N + 3) & 3];
        BF_ENCRYPT;
        *(ptr - 4) = L;
        *(ptr - 3) = R;

        L ^= data.binary.salt[(BF_N + 4) & 3];
        R ^= data.binary.salt[(BF_N + 5) & 3];
        BF_ENCRYPT;
        *(ptr - 2) = L;
        *(ptr - 1) = R;
    } while (ptr < &data.ctx.S[3][0xFF]);

    do
    {
        data.ctx.P[0] ^= data.expanded_key[0];
        data.ctx.P[1] ^= data.expanded_key[1];
        data.ctx.P[2] ^= data.expanded_key[2];
        data.ctx.P[3] ^= data.expanded_key[3];
        data.ctx.P[4] ^= data.expanded_key[4];
        data.ctx.P[5] ^= data.expanded_key[5];
        data.ctx.P[6] ^= data.expanded_key[6];
        data.ctx.P[7] ^= data.expanded_key[7];
        data.ctx.P[8] ^= data.expanded_key[8];
        data.ctx.P[9] ^= data.expanded_key[9];
        data.ctx.P[10] ^= data.expanded_key[10];
        data.ctx.P[11] ^= data.expanded_key[11];
        data.ctx.P[12] ^= data.expanded_key[12];
        data.ctx.P[13] ^= data.expanded_key[13];
        data.ctx.P[14] ^= data.expanded_key[14];
        data.ctx.P[15] ^= data.expanded_key[15];
        data.ctx.P[16] ^= data.expanded_key[16];
        data.ctx.P[17] ^= data.expanded_key[17];

        BF_body();

        tmp1 = data.binary.salt[0];
        tmp2 = data.binary.salt[1];
        tmp3 = data.binary.salt[2];
        tmp4 = data.binary.salt[3];
        data.ctx.P[0] ^= tmp1;
        data.ctx.P[1] ^= tmp2;
        data.ctx.P[2] ^= tmp3;
        data.ctx.P[3] ^= tmp4;
        data.ctx.P[4] ^= tmp1;
        data.ctx.P[5] ^= tmp2;
        data.ctx.P[6] ^= tmp3;
        data.ctx.P[7] ^= tmp4;
        data.ctx.P[8] ^= tmp1;
        data.ctx.P[9] ^= tmp2;
        data.ctx.P[10] ^= tmp3;
        data.ctx.P[11] ^= tmp4;
        data.ctx.P[12] ^= tmp1;
        data.ctx.P[13] ^= tmp2;
        data.ctx.P[14] ^= tmp3;
        data.ctx.P[15] ^= tmp4;
        data.ctx.P[16] ^= tmp1;
        data.ctx.P[17] ^= tmp2;

        BF_body();
    } while (--count);

    for (i = 0; i < 6; i += 2)
    {
        L = BF_magic_w[i];
        R = BF_magic_w[i + 1];

        count = 64;
        do
        {
            BF_ENCRYPT;
        } while (--count);

        data.binary.output[i] = L;
        data.binary.output[i + 1] = R;
    }

    memcpy(output, setting, 7 + 22 - 1);
    output[7 + 22 - 1] = BF_itoa64[(int)
                         BF_atoi64[(int) setting[7 + 22 - 1] - 0x20] & 0x30];

/* This has to be bug-compatible with the original implementation, so
 * only encode 23 of the 24 bytes. :-) */
    BF_swap(data.binary.output, 6);
    BF_encode(&output[7 + 22], data.binary.output, 23);
    output[7 + 22 + 31] = '\0';

/* Overwrite the most obvious sensitive data we have on the stack. Note
 * that this does not guarantee there's no sensitive data left on the
 * stack and/or in registers; I'm not aware of portable code that does. */
    memset(&data, 0, sizeof(data));

    return output;
}

char* _crypt_gensalt_blowfish_rn ( unsigned long  count,
const char *  input,
int  size,
char *  output,
int  output_size 
)

Definition at line 161 of file crypt-gensalt.c.

References BF_encode().

{
    if (size < 16 || output_size < 7 + 22 + 1 ||
        (count && (count < 4 || count > 31)))
    {
        if (output_size > 0)
            output[0] = '\0';
        return NULL;
    }

    if (!count)
        count = 5;

    output[0] = '$';
    output[1] = '2';
    output[2] = 'a';
    output[3] = '$';
    output[4] = '0' + count / 10;
    output[5] = '0' + count % 10;
    output[6] = '$';

    BF_encode(&output[7], (const BF_word *) input, 16);
    output[7 + 22] = '\0';

    return output;
}

char* _crypt_gensalt_extended_rn ( unsigned long  count,
const char *  input,
int  size,
char *  output,
int  output_size 
)

Definition at line 43 of file crypt-gensalt.c.

References _crypt_itoa64, and value.

{
    unsigned long value;

/* Even iteration counts make it easier to detect weak DES keys from a look
 * at the hash, so they should be avoided */
    if (size < 3 || output_size < 1 + 4 + 4 + 1 ||
        (count && (count > 0xffffff || !(count & 1))))
    {
        if (output_size > 0)
            output[0] = '\0';
        return NULL;
    }

    if (!count)
        count = 725;

    output[0] = '_';
    output[1] = _crypt_itoa64[count & 0x3f];
    output[2] = _crypt_itoa64[(count >> 6) & 0x3f];
    output[3] = _crypt_itoa64[(count >> 12) & 0x3f];
    output[4] = _crypt_itoa64[(count >> 18) & 0x3f];
    value = (unsigned long) (unsigned char) input[0] |
        ((unsigned long) (unsigned char) input[1] << 8) |
        ((unsigned long) (unsigned char) input[2] << 16);
    output[5] = _crypt_itoa64[value & 0x3f];
    output[6] = _crypt_itoa64[(value >> 6) & 0x3f];
    output[7] = _crypt_itoa64[(value >> 12) & 0x3f];
    output[8] = _crypt_itoa64[(value >> 18) & 0x3f];
    output[9] = '\0';

    return output;
}

char* _crypt_gensalt_md5_rn ( unsigned long  count,
const char *  input,
int  size,
char *  output,
int  output_size 
)

Definition at line 79 of file crypt-gensalt.c.

References _crypt_itoa64, and value.

{
    unsigned long value;

    if (size < 3 || output_size < 3 + 4 + 1 || (count && count != 1000))
    {
        if (output_size > 0)
            output[0] = '\0';
        return NULL;
    }

    output[0] = '$';
    output[1] = '1';
    output[2] = '$';
    value = (unsigned long) (unsigned char) input[0] |
        ((unsigned long) (unsigned char) input[1] << 8) |
        ((unsigned long) (unsigned char) input[2] << 16);
    output[3] = _crypt_itoa64[value & 0x3f];
    output[4] = _crypt_itoa64[(value >> 6) & 0x3f];
    output[5] = _crypt_itoa64[(value >> 12) & 0x3f];
    output[6] = _crypt_itoa64[(value >> 18) & 0x3f];
    output[7] = '\0';

    if (size >= 6 && output_size >= 3 + 4 + 4 + 1)
    {
        value = (unsigned long) (unsigned char) input[3] |
            ((unsigned long) (unsigned char) input[4] << 8) |
            ((unsigned long) (unsigned char) input[5] << 16);
        output[7] = _crypt_itoa64[value & 0x3f];
        output[8] = _crypt_itoa64[(value >> 6) & 0x3f];
        output[9] = _crypt_itoa64[(value >> 12) & 0x3f];
        output[10] = _crypt_itoa64[(value >> 18) & 0x3f];
        output[11] = '\0';
    }

    return output;
}

char* _crypt_gensalt_traditional_rn ( unsigned long  count,
const char *  input,
int  size,
char *  output,
int  output_size 
)

Definition at line 25 of file crypt-gensalt.c.

References _crypt_itoa64.

{
    if (size < 2 || output_size < 2 + 1 || (count && count != 25))
    {
        if (output_size > 0)
            output[0] = '\0';
        return NULL;
    }

    output[0] = _crypt_itoa64[(unsigned int) input[0] & 0x3f];
    output[1] = _crypt_itoa64[(unsigned int) input[1] & 0x3f];
    output[2] = '\0';

    return output;
}

char* px_crypt ( const char *  psw,
const char *  salt,
char *  buf,
unsigned  buflen 
)

Definition at line 91 of file px-crypt.c.

References px_crypt_algo::crypt, px_crypt_algo::id, px_crypt_algo::id_len, and NULL.

Referenced by pg_crypt().

{
    const struct px_crypt_algo *c;

    for (c = px_crypt_list; c->id; c++)
    {
        if (!c->id_len)
            break;
        if (strncmp(salt, c->id, c->id_len) == 0)
            break;
    }

    if (c->crypt == NULL)
        return NULL;

    return c->crypt(psw, salt, buf, len);
}

char* px_crypt_des ( const char *  key,
const char *  setting 
)

Definition at line 649 of file crypt-des.c.

References _crypt_a64, _PASSWORD_EFMT1, ascii_to_bin(), des_cipher(), des_init(), des_initialised, des_setkey(), do_des(), i, NULL, output(), and setup_salt().

Referenced by run_crypt_des().

{
    int         i;
    uint32      count,
                salt,
                l,
                r0,
                r1,
                keybuf[2];
    char       *p;
    uint8      *q;
    static char output[21];

    if (!des_initialised)
        des_init();


    /*
     * Copy the key, shifting each character up by one bit and padding with
     * zeros.
     */
    q = (uint8 *) keybuf;
    while (q - (uint8 *) keybuf - 8)
    {
        *q++ = *key << 1;
        if (*key != '\0')
            key++;
    }
    if (des_setkey((char *) keybuf))
        return (NULL);

#ifndef DISABLE_XDES
    if (*setting == _PASSWORD_EFMT1)
    {
        /*
         * "new"-style: setting - underscore, 4 bytes of count, 4 bytes of
         * salt key - unlimited characters
         */
        for (i = 1, count = 0L; i < 5; i++)
            count |= ascii_to_bin(setting[i]) << (i - 1) * 6;

        for (i = 5, salt = 0L; i < 9; i++)
            salt |= ascii_to_bin(setting[i]) << (i - 5) * 6;

        while (*key)
        {
            /*
             * Encrypt the key with itself.
             */
            if (des_cipher((char *) keybuf, (char *) keybuf, 0L, 1))
                return (NULL);

            /*
             * And XOR with the next 8 characters of the key.
             */
            q = (uint8 *) keybuf;
            while (q - (uint8 *) keybuf - 8 && *key)
                *q++ ^= *key++ << 1;

            if (des_setkey((char *) keybuf))
                return (NULL);
        }
        strncpy(output, setting, 9);

        /*
         * Double check that we weren't given a short setting. If we were, the
         * above code will probably have created weird values for count and
         * salt, but we don't really care. Just make sure the output string
         * doesn't have an extra NUL in it.
         */
        output[9] = '\0';
        p = output + strlen(output);
    }
    else
#endif   /* !DISABLE_XDES */
    {
        /*
         * "old"-style: setting - 2 bytes of salt key - up to 8 characters
         */
        count = 25;

        salt = (ascii_to_bin(setting[1]) << 6)
            | ascii_to_bin(setting[0]);

        output[0] = setting[0];

        /*
         * If the encrypted password that the salt was extracted from is only
         * 1 character long, the salt will be corrupted.  We need to ensure
         * that the output string doesn't have an extra NUL in it!
         */
        output[1] = setting[1] ? setting[1] : output[0];

        p = output + 2;
    }
    setup_salt(salt);

    /*
     * Do it.
     */
    if (do_des(0L, 0L, &r0, &r1, count))
        return (NULL);

    /*
     * Now encode the result...
     */
    l = (r0 >> 8);
    *p++ = _crypt_a64[(l >> 18) & 0x3f];
    *p++ = _crypt_a64[(l >> 12) & 0x3f];
    *p++ = _crypt_a64[(l >> 6) & 0x3f];
    *p++ = _crypt_a64[l & 0x3f];

    l = (r0 << 16) | ((r1 >> 16) & 0xffff);
    *p++ = _crypt_a64[(l >> 18) & 0x3f];
    *p++ = _crypt_a64[(l >> 12) & 0x3f];
    *p++ = _crypt_a64[(l >> 6) & 0x3f];
    *p++ = _crypt_a64[l & 0x3f];

    l = r1 << 2;
    *p++ = _crypt_a64[(l >> 12) & 0x3f];
    *p++ = _crypt_a64[(l >> 6) & 0x3f];
    *p++ = _crypt_a64[l & 0x3f];
    *p = 0;

    return (output);
}

char* px_crypt_md5 ( const char *  pw,
const char *  salt,
char *  dst,
unsigned  dstlen 
)

Definition at line 34 of file crypt-md5.c.

References _crypt_to64(), i, MD5_SIZE, px_find_digest(), px_md_finish, px_md_free, px_md_reset, and px_md_update.

Referenced by run_crypt_md5().

{
    static char *magic = "$1$"; /* This string is magic for this algorithm.
                                 * Having it this way, we can get better later
                                 * on */
    static char *p;
    static const char *sp,
               *ep;
    unsigned char final[MD5_SIZE];
    int         sl,
                pl,
                i;
    PX_MD      *ctx,
               *ctx1;
    int         err;
    unsigned long l;

    if (!passwd || dstlen < 120)
        return NULL;

    /* Refine the Salt first */
    sp = salt;

    /* If it starts with the magic string, then skip that */
    if (strncmp(sp, magic, strlen(magic)) == 0)
        sp += strlen(magic);

    /* It stops at the first '$', max 8 chars */
    for (ep = sp; *ep && *ep != '$' && ep < (sp + 8); ep++)
        continue;

    /* get the length of the true salt */
    sl = ep - sp;

    /* */
    err = px_find_digest("md5", &ctx);
    if (err)
        return NULL;
    err = px_find_digest("md5", &ctx1);

    /* The password first, since that is what is most unknown */
    px_md_update(ctx, (const uint8 *) pw, strlen(pw));

    /* Then our magic string */
    px_md_update(ctx, (uint8 *) magic, strlen(magic));

    /* Then the raw salt */
    px_md_update(ctx, (const uint8 *) sp, sl);

    /* Then just as many characters of the MD5(pw,salt,pw) */
    px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
    px_md_update(ctx1, (const uint8 *) sp, sl);
    px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
    px_md_finish(ctx1, final);
    for (pl = strlen(pw); pl > 0; pl -= MD5_SIZE)
        px_md_update(ctx, final, pl > MD5_SIZE ? MD5_SIZE : pl);

    /* Don't leave anything around in vm they could use. */
    memset(final, 0, sizeof final);

    /* Then something really weird... */
    for (i = strlen(pw); i; i >>= 1)
        if (i & 1)
            px_md_update(ctx, final, 1);
        else
            px_md_update(ctx, (const uint8 *) pw, 1);

    /* Now make the output string */
    strcpy(passwd, magic);
    strncat(passwd, sp, sl);
    strcat(passwd, "$");

    px_md_finish(ctx, final);

    /*
     * and now, just to make sure things don't run too fast On a 60 Mhz
     * Pentium this takes 34 msec, so you would need 30 seconds to build a
     * 1000 entry dictionary...
     */
    for (i = 0; i < 1000; i++)
    {
        px_md_reset(ctx1);
        if (i & 1)
            px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
        else
            px_md_update(ctx1, final, MD5_SIZE);

        if (i % 3)
            px_md_update(ctx1, (const uint8 *) sp, sl);

        if (i % 7)
            px_md_update(ctx1, (const uint8 *) pw, strlen(pw));

        if (i & 1)
            px_md_update(ctx1, final, MD5_SIZE);
        else
            px_md_update(ctx1, (const uint8 *) pw, strlen(pw));
        px_md_finish(ctx1, final);
    }

    p = passwd + strlen(passwd);

    l = (final[0] << 16) | (final[6] << 8) | final[12];
    _crypt_to64(p, l, 4);
    p += 4;
    l = (final[1] << 16) | (final[7] << 8) | final[13];
    _crypt_to64(p, l, 4);
    p += 4;
    l = (final[2] << 16) | (final[8] << 8) | final[14];
    _crypt_to64(p, l, 4);
    p += 4;
    l = (final[3] << 16) | (final[9] << 8) | final[15];
    _crypt_to64(p, l, 4);
    p += 4;
    l = (final[4] << 16) | (final[10] << 8) | final[5];
    _crypt_to64(p, l, 4);
    p += 4;
    l = final[11];
    _crypt_to64(p, l, 2);
    p += 2;
    *p = '\0';

    /* Don't leave anything around in vm they could use. */
    memset(final, 0, sizeof final);

    px_md_free(ctx1);
    px_md_free(ctx);

    return passwd;
}

int px_gen_salt ( const char *  salt_type,
char *  dst,
int  rounds 
)

Definition at line 133 of file px-crypt.c.

References generator::def_rounds, generator::gen, generator::input_len, generator::max_rounds, generator::min_rounds, generator::name, NULL, pg_strcasecmp(), px_get_pseudo_random_bytes(), and PX_MAX_SALT_LEN.

Referenced by pg_gen_salt(), and pg_gen_salt_rounds().

{
    int         res;
    struct generator *g;
    char       *p;
    char        rbuf[16];

    for (g = gen_list; g->name; g++)
        if (pg_strcasecmp(g->name, salt_type) == 0)
            break;

    if (g->name == NULL)
        return PXE_UNKNOWN_SALT_ALGO;

    if (g->def_rounds)
    {
        if (rounds == 0)
            rounds = g->def_rounds;

        if (rounds < g->min_rounds || rounds > g->max_rounds)
            return PXE_BAD_SALT_ROUNDS;
    }

    res = px_get_pseudo_random_bytes((uint8 *) rbuf, g->input_len);
    if (res < 0)
        return res;

    p = g->gen(rounds, rbuf, g->input_len, buf, PX_MAX_SALT_LEN);
    memset(rbuf, 0, sizeof(rbuf));

    if (p == NULL)
        return PXE_BAD_SALT_ROUNDS;

    return strlen(p);
}