xref: /optee_os/core/lib/libtomcrypt/src/hashes/md2.c (revision 8411e6ad673d20c4742ed30c785e3f5cdea54dfa)
1*8411e6adSJerome Forissier /* LibTomCrypt, modular cryptographic library -- Tom St Denis */
2*8411e6adSJerome Forissier /* SPDX-License-Identifier: Unlicense */
35a913ee7SJerome Forissier #include "tomcrypt_private.h"
45a913ee7SJerome Forissier 
55a913ee7SJerome Forissier /**
65a913ee7SJerome Forissier    @param md2.c
75a913ee7SJerome Forissier    LTC_MD2 (RFC 1319) hash function implementation by Tom St Denis
85a913ee7SJerome Forissier */
95a913ee7SJerome Forissier 
105a913ee7SJerome Forissier #ifdef LTC_MD2
115a913ee7SJerome Forissier 
125a913ee7SJerome Forissier const struct ltc_hash_descriptor md2_desc =
135a913ee7SJerome Forissier {
145a913ee7SJerome Forissier     "md2",
155a913ee7SJerome Forissier     7,
165a913ee7SJerome Forissier     16,
175a913ee7SJerome Forissier     16,
185a913ee7SJerome Forissier 
195a913ee7SJerome Forissier     /* OID */
205a913ee7SJerome Forissier    { 1, 2, 840, 113549, 2, 2,  },
215a913ee7SJerome Forissier    6,
225a913ee7SJerome Forissier 
235a913ee7SJerome Forissier     &md2_init,
245a913ee7SJerome Forissier     &md2_process,
255a913ee7SJerome Forissier     &md2_done,
265a913ee7SJerome Forissier     &md2_test,
275a913ee7SJerome Forissier     NULL
285a913ee7SJerome Forissier };
295a913ee7SJerome Forissier 
305a913ee7SJerome Forissier static const unsigned char PI_SUBST[256] = {
315a913ee7SJerome Forissier   41, 46, 67, 201, 162, 216, 124, 1, 61, 54, 84, 161, 236, 240, 6,
325a913ee7SJerome Forissier   19, 98, 167, 5, 243, 192, 199, 115, 140, 152, 147, 43, 217, 188,
335a913ee7SJerome Forissier   76, 130, 202, 30, 155, 87, 60, 253, 212, 224, 22, 103, 66, 111, 24,
345a913ee7SJerome Forissier   138, 23, 229, 18, 190, 78, 196, 214, 218, 158, 222, 73, 160, 251,
355a913ee7SJerome Forissier   245, 142, 187, 47, 238, 122, 169, 104, 121, 145, 21, 178, 7, 63,
365a913ee7SJerome Forissier   148, 194, 16, 137, 11, 34, 95, 33, 128, 127, 93, 154, 90, 144, 50,
375a913ee7SJerome Forissier   39, 53, 62, 204, 231, 191, 247, 151, 3, 255, 25, 48, 179, 72, 165,
385a913ee7SJerome Forissier   181, 209, 215, 94, 146, 42, 172, 86, 170, 198, 79, 184, 56, 210,
395a913ee7SJerome Forissier   150, 164, 125, 182, 118, 252, 107, 226, 156, 116, 4, 241, 69, 157,
405a913ee7SJerome Forissier   112, 89, 100, 113, 135, 32, 134, 91, 207, 101, 230, 45, 168, 2, 27,
415a913ee7SJerome Forissier   96, 37, 173, 174, 176, 185, 246, 28, 70, 97, 105, 52, 64, 126, 15,
425a913ee7SJerome Forissier   85, 71, 163, 35, 221, 81, 175, 58, 195, 92, 249, 206, 186, 197,
435a913ee7SJerome Forissier   234, 38, 44, 83, 13, 110, 133, 40, 132, 9, 211, 223, 205, 244, 65,
445a913ee7SJerome Forissier   129, 77, 82, 106, 220, 55, 200, 108, 193, 171, 250, 36, 225, 123,
455a913ee7SJerome Forissier   8, 12, 189, 177, 74, 120, 136, 149, 139, 227, 99, 232, 109, 233,
465a913ee7SJerome Forissier   203, 213, 254, 59, 0, 29, 57, 242, 239, 183, 14, 102, 88, 208, 228,
475a913ee7SJerome Forissier   166, 119, 114, 248, 235, 117, 75, 10, 49, 68, 80, 180, 143, 237,
485a913ee7SJerome Forissier   31, 26, 219, 153, 141, 51, 159, 17, 131, 20
495a913ee7SJerome Forissier };
505a913ee7SJerome Forissier 
515a913ee7SJerome Forissier /* adds 16 bytes to the checksum */
s_md2_update_chksum(hash_state * md)52*8411e6adSJerome Forissier static void s_md2_update_chksum(hash_state *md)
535a913ee7SJerome Forissier {
545a913ee7SJerome Forissier    int j;
555a913ee7SJerome Forissier    unsigned char L;
565a913ee7SJerome Forissier    L = md->md2.chksum[15];
575a913ee7SJerome Forissier    for (j = 0; j < 16; j++) {
585a913ee7SJerome Forissier 
595a913ee7SJerome Forissier /* caution, the RFC says its "C[j] = S[M[i*16+j] xor L]" but the reference source code [and test vectors] say
605a913ee7SJerome Forissier    otherwise.
615a913ee7SJerome Forissier */
625a913ee7SJerome Forissier        L = (md->md2.chksum[j] ^= PI_SUBST[(int)(md->md2.buf[j] ^ L)] & 255);
635a913ee7SJerome Forissier    }
645a913ee7SJerome Forissier }
655a913ee7SJerome Forissier 
s_md2_compress(hash_state * md)66*8411e6adSJerome Forissier static void s_md2_compress(hash_state *md)
675a913ee7SJerome Forissier {
685a913ee7SJerome Forissier    int j, k;
695a913ee7SJerome Forissier    unsigned char t;
705a913ee7SJerome Forissier 
715a913ee7SJerome Forissier    /* copy block */
725a913ee7SJerome Forissier    for (j = 0; j < 16; j++) {
735a913ee7SJerome Forissier        md->md2.X[16+j] = md->md2.buf[j];
745a913ee7SJerome Forissier        md->md2.X[32+j] = md->md2.X[j] ^ md->md2.X[16+j];
755a913ee7SJerome Forissier    }
765a913ee7SJerome Forissier 
775a913ee7SJerome Forissier    t = (unsigned char)0;
785a913ee7SJerome Forissier 
795a913ee7SJerome Forissier    /* do 18 rounds */
805a913ee7SJerome Forissier    for (j = 0; j < 18; j++) {
815a913ee7SJerome Forissier        for (k = 0; k < 48; k++) {
825a913ee7SJerome Forissier            t = (md->md2.X[k] ^= PI_SUBST[(int)(t & 255)]);
835a913ee7SJerome Forissier        }
845a913ee7SJerome Forissier        t = (t + (unsigned char)j) & 255;
855a913ee7SJerome Forissier    }
865a913ee7SJerome Forissier }
875a913ee7SJerome Forissier 
885a913ee7SJerome Forissier /**
895a913ee7SJerome Forissier    Initialize the hash state
905a913ee7SJerome Forissier    @param md   The hash state you wish to initialize
915a913ee7SJerome Forissier    @return CRYPT_OK if successful
925a913ee7SJerome Forissier */
md2_init(hash_state * md)935a913ee7SJerome Forissier int md2_init(hash_state *md)
945a913ee7SJerome Forissier {
955a913ee7SJerome Forissier    LTC_ARGCHK(md != NULL);
965a913ee7SJerome Forissier 
975a913ee7SJerome Forissier    /* LTC_MD2 uses a zero'ed state... */
985a913ee7SJerome Forissier    zeromem(md->md2.X, sizeof(md->md2.X));
995a913ee7SJerome Forissier    zeromem(md->md2.chksum, sizeof(md->md2.chksum));
1005a913ee7SJerome Forissier    zeromem(md->md2.buf, sizeof(md->md2.buf));
1015a913ee7SJerome Forissier    md->md2.curlen = 0;
1025a913ee7SJerome Forissier    return CRYPT_OK;
1035a913ee7SJerome Forissier }
1045a913ee7SJerome Forissier 
1055a913ee7SJerome Forissier /**
1065a913ee7SJerome Forissier    Process a block of memory though the hash
1075a913ee7SJerome Forissier    @param md     The hash state
1085a913ee7SJerome Forissier    @param in     The data to hash
1095a913ee7SJerome Forissier    @param inlen  The length of the data (octets)
1105a913ee7SJerome Forissier    @return CRYPT_OK if successful
1115a913ee7SJerome Forissier */
md2_process(hash_state * md,const unsigned char * in,unsigned long inlen)1125a913ee7SJerome Forissier int md2_process(hash_state *md, const unsigned char *in, unsigned long inlen)
1135a913ee7SJerome Forissier {
1145a913ee7SJerome Forissier     unsigned long n;
1155a913ee7SJerome Forissier     LTC_ARGCHK(md != NULL);
1165a913ee7SJerome Forissier     LTC_ARGCHK(in != NULL);
1175a913ee7SJerome Forissier     if (md-> md2 .curlen > sizeof(md-> md2 .buf)) {
1185a913ee7SJerome Forissier        return CRYPT_INVALID_ARG;
1195a913ee7SJerome Forissier     }
1205a913ee7SJerome Forissier     while (inlen > 0) {
1215a913ee7SJerome Forissier         n = MIN(inlen, (16 - md->md2.curlen));
1225a913ee7SJerome Forissier         XMEMCPY(md->md2.buf + md->md2.curlen, in, (size_t)n);
1235a913ee7SJerome Forissier         md->md2.curlen += n;
1245a913ee7SJerome Forissier         in             += n;
1255a913ee7SJerome Forissier         inlen          -= n;
1265a913ee7SJerome Forissier 
1275a913ee7SJerome Forissier         /* is 16 bytes full? */
1285a913ee7SJerome Forissier         if (md->md2.curlen == 16) {
129*8411e6adSJerome Forissier             s_md2_compress(md);
130*8411e6adSJerome Forissier             s_md2_update_chksum(md);
1315a913ee7SJerome Forissier             md->md2.curlen = 0;
1325a913ee7SJerome Forissier         }
1335a913ee7SJerome Forissier     }
1345a913ee7SJerome Forissier     return CRYPT_OK;
1355a913ee7SJerome Forissier }
1365a913ee7SJerome Forissier 
1375a913ee7SJerome Forissier /**
1385a913ee7SJerome Forissier    Terminate the hash to get the digest
1395a913ee7SJerome Forissier    @param md  The hash state
1405a913ee7SJerome Forissier    @param out [out] The destination of the hash (16 bytes)
1415a913ee7SJerome Forissier    @return CRYPT_OK if successful
1425a913ee7SJerome Forissier */
md2_done(hash_state * md,unsigned char * out)1435a913ee7SJerome Forissier int md2_done(hash_state * md, unsigned char *out)
1445a913ee7SJerome Forissier {
1455a913ee7SJerome Forissier     unsigned long i, k;
1465a913ee7SJerome Forissier 
1475a913ee7SJerome Forissier     LTC_ARGCHK(md  != NULL);
1485a913ee7SJerome Forissier     LTC_ARGCHK(out != NULL);
1495a913ee7SJerome Forissier 
1505a913ee7SJerome Forissier     if (md->md2.curlen >= sizeof(md->md2.buf)) {
1515a913ee7SJerome Forissier        return CRYPT_INVALID_ARG;
1525a913ee7SJerome Forissier     }
1535a913ee7SJerome Forissier 
1545a913ee7SJerome Forissier 
1555a913ee7SJerome Forissier     /* pad the message */
1565a913ee7SJerome Forissier     k = 16 - md->md2.curlen;
1575a913ee7SJerome Forissier     for (i = md->md2.curlen; i < 16; i++) {
1585a913ee7SJerome Forissier         md->md2.buf[i] = (unsigned char)k;
1595a913ee7SJerome Forissier     }
1605a913ee7SJerome Forissier 
1615a913ee7SJerome Forissier     /* hash and update */
162*8411e6adSJerome Forissier     s_md2_compress(md);
163*8411e6adSJerome Forissier     s_md2_update_chksum(md);
1645a913ee7SJerome Forissier 
1655a913ee7SJerome Forissier     /* hash checksum */
1665a913ee7SJerome Forissier     XMEMCPY(md->md2.buf, md->md2.chksum, 16);
167*8411e6adSJerome Forissier     s_md2_compress(md);
1685a913ee7SJerome Forissier 
1695a913ee7SJerome Forissier     /* output is lower 16 bytes of X */
1705a913ee7SJerome Forissier     XMEMCPY(out, md->md2.X, 16);
1715a913ee7SJerome Forissier 
1725a913ee7SJerome Forissier #ifdef LTC_CLEAN_STACK
1735a913ee7SJerome Forissier     zeromem(md, sizeof(hash_state));
1745a913ee7SJerome Forissier #endif
1755a913ee7SJerome Forissier     return CRYPT_OK;
1765a913ee7SJerome Forissier }
1775a913ee7SJerome Forissier 
1785a913ee7SJerome Forissier /**
1795a913ee7SJerome Forissier   Self-test the hash
1805a913ee7SJerome Forissier   @return CRYPT_OK if successful, CRYPT_NOP if self-tests have been disabled
1815a913ee7SJerome Forissier */
md2_test(void)1825a913ee7SJerome Forissier int md2_test(void)
1835a913ee7SJerome Forissier {
1845a913ee7SJerome Forissier  #ifndef LTC_TEST
1855a913ee7SJerome Forissier     return CRYPT_NOP;
1865a913ee7SJerome Forissier  #else
1875a913ee7SJerome Forissier    static const struct {
1885a913ee7SJerome Forissier         const char *msg;
1895a913ee7SJerome Forissier         unsigned char hash[16];
1905a913ee7SJerome Forissier    } tests[] = {
1915a913ee7SJerome Forissier       { "",
1925a913ee7SJerome Forissier         {0x83,0x50,0xe5,0xa3,0xe2,0x4c,0x15,0x3d,
1935a913ee7SJerome Forissier          0xf2,0x27,0x5c,0x9f,0x80,0x69,0x27,0x73
1945a913ee7SJerome Forissier         }
1955a913ee7SJerome Forissier       },
1965a913ee7SJerome Forissier       { "a",
1975a913ee7SJerome Forissier         {0x32,0xec,0x01,0xec,0x4a,0x6d,0xac,0x72,
1985a913ee7SJerome Forissier          0xc0,0xab,0x96,0xfb,0x34,0xc0,0xb5,0xd1
1995a913ee7SJerome Forissier         }
2005a913ee7SJerome Forissier       },
2015a913ee7SJerome Forissier       { "message digest",
2025a913ee7SJerome Forissier         {0xab,0x4f,0x49,0x6b,0xfb,0x2a,0x53,0x0b,
2035a913ee7SJerome Forissier          0x21,0x9f,0xf3,0x30,0x31,0xfe,0x06,0xb0
2045a913ee7SJerome Forissier         }
2055a913ee7SJerome Forissier       },
2065a913ee7SJerome Forissier       { "abcdefghijklmnopqrstuvwxyz",
2075a913ee7SJerome Forissier         {0x4e,0x8d,0xdf,0xf3,0x65,0x02,0x92,0xab,
2085a913ee7SJerome Forissier          0x5a,0x41,0x08,0xc3,0xaa,0x47,0x94,0x0b
2095a913ee7SJerome Forissier         }
2105a913ee7SJerome Forissier       },
2115a913ee7SJerome Forissier       { "ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789",
2125a913ee7SJerome Forissier         {0xda,0x33,0xde,0xf2,0xa4,0x2d,0xf1,0x39,
2135a913ee7SJerome Forissier          0x75,0x35,0x28,0x46,0xc3,0x03,0x38,0xcd
2145a913ee7SJerome Forissier         }
2155a913ee7SJerome Forissier       },
2165a913ee7SJerome Forissier       { "12345678901234567890123456789012345678901234567890123456789012345678901234567890",
2175a913ee7SJerome Forissier         {0xd5,0x97,0x6f,0x79,0xd8,0x3d,0x3a,0x0d,
2185a913ee7SJerome Forissier          0xc9,0x80,0x6c,0x3c,0x66,0xf3,0xef,0xd8
2195a913ee7SJerome Forissier         }
2205a913ee7SJerome Forissier       }
2215a913ee7SJerome Forissier    };
2225a913ee7SJerome Forissier 
2235a913ee7SJerome Forissier    int i;
2245a913ee7SJerome Forissier    unsigned char tmp[16];
2255a913ee7SJerome Forissier    hash_state md;
2265a913ee7SJerome Forissier 
2275a913ee7SJerome Forissier    for (i = 0; i < (int)(sizeof(tests) / sizeof(tests[0])); i++) {
2285a913ee7SJerome Forissier        md2_init(&md);
229*8411e6adSJerome Forissier        md2_process(&md, (unsigned char*)tests[i].msg, (unsigned long)XSTRLEN(tests[i].msg));
2305a913ee7SJerome Forissier        md2_done(&md, tmp);
2315a913ee7SJerome Forissier        if (compare_testvector(tmp, sizeof(tmp), tests[i].hash, sizeof(tests[i].hash), "MD2", i)) {
2325a913ee7SJerome Forissier           return CRYPT_FAIL_TESTVECTOR;
2335a913ee7SJerome Forissier        }
2345a913ee7SJerome Forissier    }
2355a913ee7SJerome Forissier    return CRYPT_OK;
2365a913ee7SJerome Forissier   #endif
2375a913ee7SJerome Forissier }
2385a913ee7SJerome Forissier 
2395a913ee7SJerome Forissier #endif
2405a913ee7SJerome Forissier 
241