Annotation of truecrypt/common/pkcs5.c, revision 1.1.1.1

1.1       root        1: /* Copyright (C) 2004 TrueCrypt Team, truecrypt.org
                      2:    This product uses components written by Paul Le Roux <[email protected]> */
                      3: 
                      4: #include "TCdefs.h"
                      5: 
                      6: #include <memory.h>
                      7: #include "sha1.h"
                      8: #include "md5.h"
                      9: #include "pkcs5.h"
                     10: 
                     11: void truncate
                     12:   (
                     13:          char *d1,             /* data to be truncated */
                     14:          char *d2,             /* truncated data */
                     15:          int len               /* length in bytes to keep */
                     16: )
                     17: {
                     18:        int i;
                     19:        for (i = 0; i < len; i++)
                     20:                d2[i] = d1[i];
                     21: }
                     22: 
                     23: 
                     24: /* Function to compute the digest */
                     25: void
                     26:   hmac_sha
                     27:   (
                     28:          char *k,              /* secret key */
                     29:          int lk,               /* length of the key in bytes */
                     30:          char *d,              /* data */
                     31:          int ld,               /* length of data in bytes */
                     32:          char *out,            /* output buffer, at least "t" bytes */
                     33:          int t
                     34: )
                     35: {
                     36:        SHA1_CTX ictx, octx;
                     37:        char isha[SHA_DIGESTSIZE], osha[SHA_DIGESTSIZE];
                     38:        char key[SHA_DIGESTSIZE];
                     39:        char buf[SHA_BLOCKSIZE];
                     40:        int i;
                     41: 
                     42:        if (lk > SHA_BLOCKSIZE)
                     43:        {
                     44: 
                     45:                SHA1_CTX tctx;
                     46: 
                     47:                SHA1Init (&tctx);
                     48:                SHA1Update (&tctx, (unsigned char *) k, lk);
                     49:                SHA1Final ((unsigned char *) key, &tctx);
                     50: 
                     51:                k = key;
                     52:                lk = SHA_DIGESTSIZE;
                     53:        }
                     54: 
                     55:        /**** Inner Digest ****/
                     56: 
                     57:        SHA1Init (&ictx);
                     58: 
                     59:        /* Pad the key for inner digest */
                     60:        for (i = 0; i < lk; ++i)
                     61:                buf[i] = (char) (k[i] ^ 0x36);
                     62:        for (i = lk; i < SHA_BLOCKSIZE; ++i)
                     63:                buf[i] = 0x36;
                     64: 
                     65:        SHA1Update (&ictx, (unsigned char *) buf, SHA_BLOCKSIZE);
                     66:        SHA1Update (&ictx, (unsigned char *) d, ld);
                     67: 
                     68:        SHA1Final ((unsigned char *) isha, &ictx);
                     69: 
                     70:        /**** Outter Digest ****/
                     71: 
                     72:        SHA1Init (&octx);
                     73: 
                     74:        for (i = 0; i < lk; ++i)
                     75:                buf[i] = (char) (k[i] ^ 0x5C);
                     76:        for (i = lk; i < SHA_BLOCKSIZE; ++i)
                     77:                buf[i] = 0x5C;
                     78: 
                     79:        SHA1Update (&octx, (unsigned char *) buf, SHA_BLOCKSIZE);
                     80:        SHA1Update (&octx, (unsigned char *) isha, SHA_DIGESTSIZE);
                     81: 
                     82:        SHA1Final ((unsigned char *) osha, &octx);
                     83: 
                     84:        /* truncate and print the results */
                     85:        t = t > SHA_DIGESTSIZE ? SHA_DIGESTSIZE : t;
                     86:        truncate (osha, out, t);
                     87: }
                     88: 
                     89: 
                     90: void
                     91: derive_u_sha (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b)
                     92: {
                     93:        char j[SHA_DIGESTSIZE], k[SHA_DIGESTSIZE];
                     94:        char init[128];
                     95:        char counter[4];
                     96:        int c, i;
                     97: 
                     98:        /* iteration 1 */
                     99:        memset (counter, 0, 4);
                    100:        counter[3] = (char) b;
                    101:        memcpy (init, salt, salt_len);  /* salt */
                    102:        memcpy (&init[salt_len], counter, 4);   /* big-endian block number */
                    103:        hmac_sha (pwd, pwd_len, init, salt_len + 4, j, SHA_DIGESTSIZE);
                    104:        memcpy (u, j, SHA_DIGESTSIZE);
                    105: 
                    106:        /* remaining iterations */
                    107:        for (c = 1; c < iterations; c++)
                    108:        {
                    109:                hmac_sha (pwd, pwd_len, j, SHA_DIGESTSIZE, k, SHA_DIGESTSIZE);
                    110:                for (i = 0; i < SHA_DIGESTSIZE; i++)
                    111:                {
                    112:                        u[i] ^= k[i];
                    113:                        j[i] = k[i];
                    114:                }
                    115:        }
                    116: }
                    117: 
                    118: void
                    119: derive_sha_key (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen)
                    120: {
                    121:        char u[SHA_DIGESTSIZE];
                    122:        int b, l, r;
                    123: 
                    124:        if (dklen % SHA_DIGESTSIZE)
                    125:        {
                    126:                l = 1 + dklen / SHA_DIGESTSIZE;
                    127:        }
                    128:        else
                    129:        {
                    130:                l = dklen / SHA_DIGESTSIZE;
                    131:        }
                    132: 
                    133:        r = dklen - (l - 1) * SHA_DIGESTSIZE;
                    134: 
                    135:        /* first l - 1 blocks */
                    136:        for (b = 1; b < l; b++)
                    137:        {
                    138:                derive_u_sha (pwd, pwd_len, salt, salt_len, iterations, u, b);
                    139:                memcpy (dk, u, SHA_DIGESTSIZE);
                    140:                dk += SHA_DIGESTSIZE;
                    141:        }
                    142: 
                    143:        /* last block */
                    144:        derive_u_sha (pwd, pwd_len, salt, salt_len, iterations, u, b);
                    145:        memcpy (dk, u, r);
                    146: }
                    147: 
                    148: #define MD5_DIGESTSIZE 16
                    149: 
                    150: void
                    151: hmac_md5 (char *text,          /* pointer to data stream */
                    152:          int text_len,         /* length of data stream */
                    153:          char *key,            /* pointer to authentication key */
                    154:          int key_len,          /* length of authentication key */
                    155:          char *digest)         /* caller digest to be filled in */
                    156: {
                    157:        MD5_CTX context;
                    158:        char k_ipad[65];        /* inner padding - key XORd with ipad */
                    159:        char k_opad[65];        /* outer padding - key XORd with opad */
                    160:        char tk[MD5_DIGESTSIZE];
                    161:        int i;
                    162:        /* if key is longer than 64 bytes reset it to key=MD5(key) */
                    163:        if (key_len > 64)
                    164:        {
                    165: 
                    166:                MD5_CTX tctx;
                    167: 
                    168:                MD5Init (&tctx);
                    169:                MD5Update (&tctx, (unsigned char *) key, key_len);
                    170:                MD5Final ((unsigned char *) tk, &tctx);
                    171: 
                    172:                key = tk;
                    173:                key_len = MD5_DIGESTSIZE;
                    174:        }
                    175: 
                    176:        /* the HMAC_MD5 transform looks like:
                    177:        
                    178:        MD5(K XOR opad, MD5(K XOR ipad, text))
                    179:        
                    180:        where K is an n byte key ipad is the byte 0x36 repeated 64 times opad
                    181:           is the byte 0x5c repeated 64 times and text is the data being
                    182:           protected */
                    183: 
                    184:        /* start out by storing key in pads */
                    185:        memset (k_ipad, 0, sizeof k_ipad);
                    186:        memset (k_opad, 0, sizeof k_opad);
                    187:        memcpy (k_ipad, key, key_len);
                    188:        memcpy (k_opad, key, key_len);
                    189: 
                    190:        /* XOR key with ipad and opad values */
                    191:        for (i = 0; i < 64; i++)
                    192:        {
                    193:                k_ipad[i] ^= 0x36;
                    194:                k_opad[i] ^= 0x5c;
                    195:        }
                    196: 
                    197:        /* perform inner MD5 */
                    198:        MD5Init (&context);     /* init context for 1st pass */
                    199:        MD5Update (&context, (unsigned char *) k_ipad, 64);     /* start with inner pad */
                    200:        MD5Update (&context, (unsigned char *) text, text_len); /* then text of datagram */
                    201:        MD5Final ((unsigned char *) digest, &context);  /* finish up 1st pass */
                    202:        /* perform outer MD5 */
                    203:        MD5Init (&context);     /* init context for 2nd pass */
                    204:        MD5Update (&context, (unsigned char *) k_opad, 64);     /* start with outer pad */
                    205:        MD5Update (&context, (unsigned char *) digest, MD5_DIGESTSIZE); /* then results of 1st
                    206:                                                                           hash */
                    207:        MD5Final ((unsigned char *) digest, &context);  /* finish up 2nd pass */
                    208: }
                    209: 
                    210: void
                    211: derive_u_md5 (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *u, int b)
                    212: {
                    213:        char j[MD5_DIGESTSIZE], k[MD5_DIGESTSIZE];
                    214:        char init[128];
                    215:        char counter[4];
                    216:        int c, i;
                    217: 
                    218:        /* iteration 1 */
                    219:        memset (counter, 0, 4);
                    220:        counter[3] = (char) b;
                    221:        memcpy (init, salt, salt_len);  /* salt */
                    222:        memcpy (&init[salt_len], counter, 4);   /* big-endian block number */
                    223:        hmac_md5 (pwd, pwd_len, init, salt_len + 4, j);
                    224:        memcpy (u, j, MD5_DIGESTSIZE);
                    225: 
                    226:        /* remaining iterations */
                    227:        for (c = 1; c < iterations; c++)
                    228:        {
                    229:                hmac_md5 (pwd, pwd_len, j, MD5_DIGESTSIZE, k);
                    230:                for (i = 0; i < MD5_DIGESTSIZE; i++)
                    231:                {
                    232:                        u[i] ^= k[i];
                    233:                        j[i] = k[i];
                    234:                }
                    235:        }
                    236: }
                    237: 
                    238: void
                    239: derive_md5_key (char *pwd, int pwd_len, char *salt, int salt_len, int iterations, char *dk, int dklen)
                    240: {
                    241:        char u[MD5_DIGESTSIZE];
                    242:        int b, l, r;
                    243: 
                    244:        if (dklen % MD5_DIGESTSIZE)
                    245:        {
                    246:                l = 1 + dklen / MD5_DIGESTSIZE;
                    247:        }
                    248:        else
                    249:        {
                    250:                l = dklen / MD5_DIGESTSIZE;
                    251:        }
                    252: 
                    253:        r = dklen - (l - 1) * MD5_DIGESTSIZE;
                    254: 
                    255:        /* first l - 1 blocks */
                    256:        for (b = 1; b < l; b++)
                    257:        {
                    258:                derive_u_md5 (pwd, pwd_len, salt, salt_len, iterations, u, b);
                    259:                memcpy (dk, u, MD5_DIGESTSIZE);
                    260:                dk += MD5_DIGESTSIZE;
                    261:        }
                    262: 
                    263:        /* last block */
                    264:        derive_u_md5 (pwd, pwd_len, salt, salt_len, iterations, u, b);
                    265:        memcpy (dk, u, r);
                    266: }
                    267: 
                    268: 
                    269: 
                    270: /* rfc2104 & 2202 */
                    271: 
                    272: char *hmac_test_keys[3] =
                    273: {
                    274:        "\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b\x0b",
                    275:        "Jefe",
                    276:        "\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA\xAA"
                    277: };
                    278: 
                    279: 
                    280: char *hmac_test_data[3] =
                    281: {
                    282:        "Hi There",
                    283:        "what do ya want for nothing?",
                    284:        "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
                    285:       "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
                    286:        "\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD\xDD"
                    287: };
                    288: 
                    289: char *hmac_md5_test_vectors[3] =
                    290: {
                    291:        "\x92\x94\x72\x7a\x36\x38\xbb\x1c\x13\xf4\x8e\xf8\x15\x8b\xfc\x9d",
                    292:        "\x75\x0c\x78\x3e\x6a\xb0\xb5\x03\xea\xa8\x6e\x31\x0a\x5d\xb7\x38",
                    293:        "\x56\xbe\x34\x52\x1d\x14\x4c\x88\xdb\xb8\xc7\x33\xf0\xe8\xb3\xf6"
                    294: };
                    295: 
                    296: char *hmac_sha_test_vectors[3] =
                    297: {
                    298:        "\xb6\x17\x31\x86\x55\x05\x72\x64\xe2\x8b\xc0\xb6\xfb\x37\x8c\x8e\xf1\x46\xbe\x00",
                    299:        "\xef\xfc\xdf\x6a\xe5\xeb\x2f\xa2\xd2\x74\x16\xd5\xf1\x84\xdf\x9c\x25\x9a\x7c\x79",
                    300:        "\x12\x5d\x73\x42\xb9\xac\x11\xcd\x91\xa3\x9a\xf4\x8a\xa1\x7b\x4f\x63\xf1\x75\xd3"
                    301: };
                    302: 
                    303: BOOL
                    304: test_hmac_sha1 ()
                    305: {
                    306:        BOOL bOK = TRUE;
                    307:        int i;
                    308: 
                    309:        for (i = 0; i < 3; i++)
                    310:        {
                    311:                char digest[SHA_DIGESTSIZE];
                    312:                hmac_sha (hmac_test_keys[i], strlen (hmac_test_keys[i]), hmac_test_data[i], strlen (hmac_test_data[i]), digest, SHA_DIGESTSIZE);
                    313:                if (memcmp (digest, hmac_sha_test_vectors[i], SHA_DIGESTSIZE) != 0)
                    314:                        return FALSE;
                    315:        }
                    316: 
                    317:        return TRUE;
                    318: }
                    319: 
                    320: BOOL
                    321: test_hmac_md5 ()
                    322: {
                    323:        int i;
                    324:        for (i = 0; i < 3; i++)
                    325:        {
                    326:                char digest[MD5_DIGESTSIZE];
                    327:                int x = strlen (hmac_test_keys[i]);
                    328:                hmac_md5 (hmac_test_data[i], strlen (hmac_test_data[i]), hmac_test_keys[i], x > MD5_DIGESTSIZE ? MD5_DIGESTSIZE : x, digest);
                    329:                if (memcmp (digest, hmac_md5_test_vectors[i], MD5_DIGESTSIZE) != 0)
                    330:                        return FALSE;
                    331:        }
                    332: 
                    333:        return TRUE;
                    334: }
                    335: 
                    336: BOOL
                    337: test_pkcs5 ()
                    338: {
                    339:        char dk[4];
                    340: 
                    341:        /* First make sure the hmacs are ok */
                    342:        if (test_hmac_sha1 ()== FALSE)
                    343:                return FALSE;
                    344:        if (test_hmac_md5 ()== FALSE)
                    345:                return FALSE;
                    346: 
                    347:        /* Next check the sha1 with pkcs5 */
                    348:        derive_sha_key ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
                    349:        if (memcmp (dk, "\x5c\x75\xce\xf0", 4) != 0)
                    350:                return FALSE;
                    351: 
                    352:        /* Next check md5 with pkcs5 */
                    353:        derive_md5_key ("password", 8, "\x12\x34\x56\x78", 4, 5, dk, 4);
                    354:        if (memcmp (dk, "\x91\xa9\xd7\x92", 4) != 0)
                    355:                return FALSE;
                    356: 
                    357:        return TRUE;
                    358: 
                    359: }
                    360: 

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.