Annotation of truecrypt/common/pkcs5.c, revision 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.