/* This is mostly just a wrapper around hmac_memory */ int hkdf_extract(int hash_idx, const unsigned char *salt, unsigned long saltlen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long *outlen) { /* libtomcrypt chokes on a zero length HMAC key, so we need to check for that. HMAC specifies that keys shorter than the hash's blocksize are 0 padded to the block size. HKDF specifies that a NULL salt is to be substituted with a salt comprised of hashLen 0 bytes. HMAC's padding means that in either case the HMAC is actually using a blocksize long zero filled key. Unless blocksize < hashLen (which wouldn't make any sense), we can use a single 0 byte as the HMAC key and still generate valid results for HKDF. */ if (salt == NULL || saltlen == 0) { return hmac_memory(hash_idx, (const unsigned char *)"", 1, in, inlen, out, outlen); } else { return hmac_memory(hash_idx, salt, saltlen, in, inlen, out, outlen); } }
void hmac_gen(void) { unsigned char key[MAXBLOCKSIZE], output[MAXBLOCKSIZE], *input; int x, y, z, err; FILE *out; unsigned long len; out = fopen("hmac_tv.txt", "w"); fprintf(out, "HMAC Tests. In these tests messages of N bytes long (00,01,02,...,NN-1) are HMACed. The initial key is\n" "of the same format (the same length as the HASH output size). The HMAC key in step N+1 is the HMAC output of\n" "step N.\n\n"); for (x = 0; hash_descriptor[x].name != NULL; x++) { fprintf(out, "HMAC-%s\n", hash_descriptor[x].name); /* initial key */ for (y = 0; y < (int)hash_descriptor[x].hashsize; y++) { key[y] = (y&255); } input = XMALLOC(hash_descriptor[x].blocksize * 2 + 1); if (input == NULL) { perror("Can't malloc memory"); exit(EXIT_FAILURE); } for (y = 0; y <= (int)(hash_descriptor[x].blocksize * 2); y++) { for (z = 0; z < y; z++) { input[z] = (unsigned char)(z & 255); } len = sizeof(output); if ((err = hmac_memory(x, key, hash_descriptor[x].hashsize, input, y, output, &len)) != CRYPT_OK) { printf("Error hmacing: %s\n", error_to_string(err)); exit(EXIT_FAILURE); } fprintf(out, "%3d: ", y); for (z = 0; z <(int) len; z++) { fprintf(out, "%02X", output[z]); } fprintf(out, "\n"); /* forward the key */ memcpy(key, output, hash_descriptor[x].hashsize); } XFREE(input); fprintf(out, "\n"); } fclose(out); }
/* Like hmac_memory, but verifies */ int hmac_vrfymem(int hash, const unsigned char *key, unsigned long keylen, const unsigned char *in, unsigned long inlen, const unsigned char *vrfy, unsigned long *outlen) { unsigned char *out = safe_malloc(*outlen); int err; if ((err = hmac_memory(hash, key, keylen, in, inlen, out, outlen)) != CRYPT_OK) { safe_free(out); fprintf(stderr, "hmac_vrfymem: hmac_memory failed\n"); return err; } if (memcmp(vrfy, out, *outlen) != 0) { safe_free(out); return CRYPT_ERROR; } safe_free(out); return CRYPT_OK; }
/* compatibility wrapper */ static void HMAC_SHA1( uint8_t* secret, size_t secret_len, uint8_t* in, size_t in_len, uint8_t* out) { int rv; unsigned long out_len; if (sha1_id < 0) { sha1_id = register_hash( &sha1_desc); } out_len = hash_descriptor[sha1_id].hashsize; rv = hmac_memory( sha1_id, secret, secret_len, in, in_len, out, &out_len); if (rv) { abort(); } }
/* * Computes a HMAC SHA-1 keyed hash of 'input' using the key 'key' */ bool hmacSha1(const unsigned char* key, const size_t keyLen, const unsigned char* input, const size_t inputLen, unsigned char* output, unsigned int* outputLen) { if (!key || !input || !output) { return false; } static int hashId = -1; if (hashId == -1) { register_hash(&sha1_desc); hashId = find_hash("sha1"); } unsigned long sha1HashLen = 20; if (hmac_memory(hashId, key, keyLen, input, inputLen, output, &sha1HashLen) != CRYPT_OK) { return false; } *outputLen = sha1HashLen; return true; }
int hmac_test(void) { #ifndef LTC_TEST return CRYPT_NOP; #else unsigned char digest[MAXBLOCKSIZE]; int i; static const struct hmac_test_case { int num; char *algo; unsigned char key[128]; unsigned long keylen; unsigned char data[128]; unsigned long datalen; unsigned char digest[MAXBLOCKSIZE]; } cases[] = { /* 3. Test Cases for HMAC-SHA-1 test_case = 1 key = 0x0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b key_len = 20 data = "Hi Ther 20 digest = 0x4c1a03424b55e07fe7f27be1d58bb9324a9a5a04 digest-96 = 0x4c1a03424b55e07fe7f27be1 */ { 5, "sha1", {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 20, "Test With Truncation", 20, {0x4c, 0x1a, 0x03, 0x42, 0x4b, 0x55, 0xe0, 0x7f, 0xe7, 0xf2, 0x7b, 0xe1, 0xd5, 0x8b, 0xb9, 0x32, 0x4a, 0x9a, 0x5a, 0x04} }, /* test_case = 6 key = 0xaa repeated 80 times key_len = 80 data = "Test Using Larger Than Block-Size Key - Hash Key First" data_len = 54 digest = 0xaa4ae5e15272d00e95705637ce8a3b55ed402112 */ { 6, "sha1", {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, "Test Using Larger Than Block-Size Key - Hash Key First", 54, {0xaa, 0x4a, 0xe5, 0xe1, 0x52, 0x72, 0xd0, 0x0e, 0x95, 0x70, 0x56, 0x37, 0xce, 0x8a, 0x3b, 0x55, 0xed, 0x40, 0x21, 0x12} }, /* test_case = 7 key = 0xaa repeated 80 times key_len = 80 data = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" data_len = 73 digest = 0xe8e99d0f45237d786d6bbaa7965c7808bbff1a91 */ { 7, "sha1", {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, {0xe8, 0xe9, 0x9d, 0x0f, 0x45, 0x23, 0x7d, 0x78, 0x6d, 0x6b, 0xba, 0xa7, 0x96, 0x5c, 0x78, 0x08, 0xbb, 0xff, 0x1a, 0x91} }, /* 2. Test Cases for HMAC-MD5 test_case = 1 key = 0x0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b 0b key_len = 16 data = "Hi There" data_len = 8 digest = 0x92 94 72 7a 36 38 bb 1c 13 f4 8e f8 15 8b fc 9d */ { 1, "md5", {0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b, 0x0b}, 16, "Hi There", 8, {0x92, 0x94, 0x72, 0x7a, 0x36, 0x38, 0xbb, 0x1c, 0x13, 0xf4, 0x8e, 0xf8, 0x15, 0x8b, 0xfc, 0x9d} }, /* test_case = 2 key = "Jefe" key_len = 4 data = "what do ya want for nothing?" data_len = 28 digest = 0x750c783e6ab0b503eaa86e310a5db738 */ { 2, "md5", "Jefe", 4, "what do ya want for nothing?", 28, {0x75, 0x0c, 0x78, 0x3e, 0x6a, 0xb0, 0xb5, 0x03, 0xea, 0xa8, 0x6e, 0x31, 0x0a, 0x5d, 0xb7, 0x38} }, /* test_case = 3 key = 0xaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa key_len 16 data = 0xdd repeated 50 times data_len = 50 digest = 0x56be34521d144c88dbb8c733f0e8b3f6 */ { 3, "md5", {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 16, {0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd, 0xdd}, 50, {0x56, 0xbe, 0x34, 0x52, 0x1d, 0x14, 0x4c, 0x88, 0xdb, 0xb8, 0xc7, 0x33, 0xf0, 0xe8, 0xb3, 0xf6} }, /* test_case = 4 key = 0x0102030405060708090a0b0c0d0e0f10111213141516171819 key_len 25 data = 0xcd repeated 50 times data_len = 50 digest = 0x697eaf0aca3a3aea3a75164746ffaa79 */ { 4, "md5", {0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17, 0x18, 0x19}, 25, {0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd, 0xcd}, 50, {0x69, 0x7e, 0xaf, 0x0a, 0xca, 0x3a, 0x3a, 0xea, 0x3a, 0x75, 0x16, 0x47, 0x46, 0xff, 0xaa, 0x79} }, /* test_case = 5 key = 0x0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c0c key_len = 16 data = "Test With Truncation" data_len = 20 digest = 0x56461ef2342edc00f9bab995690efd4c digest-96 0x56461ef2342edc00f9bab995 */ { 5, "md5", {0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c, 0x0c}, 16, "Test With Truncation", 20, {0x56, 0x46, 0x1e, 0xf2, 0x34, 0x2e, 0xdc, 0x00, 0xf9, 0xba, 0xb9, 0x95, 0x69, 0x0e, 0xfd, 0x4c} }, /* test_case = 6 key = 0xaa repeated 80 times key_len = 80 data = "Test Using Larger Than Block-Size Key - Hash Key First" data_len = 54 digest = 0x6b1ab7fe4bd7bf8f0b62e6ce61b9d0cd */ { 6, "md5", {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, "Test Using Larger Than Block-Size Key - Hash Key First", 54, {0x6b, 0x1a, 0xb7, 0xfe, 0x4b, 0xd7, 0xbf, 0x8f, 0x0b, 0x62, 0xe6, 0xce, 0x61, 0xb9, 0xd0, 0xcd} }, /* test_case = 7 key = 0xaa repeated 80 times key_len = 80 data = "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data" data_len = 73 digest = 0x6f630fad67cda0ee1fb1f562db3aa53e */ { 7, "md5", {0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa, 0xaa}, 80, "Test Using Larger Than Block-Size Key and Larger Than One Block-Size Data", 73, {0x6f, 0x63, 0x0f, 0xad, 0x67, 0xcd, 0xa0, 0xee, 0x1f, 0xb1, 0xf5, 0x62, 0xdb, 0x3a, 0xa5, 0x3e} } }; unsigned long outlen; int err; int tested=0,failed=0; for(i=0; i < (int)(sizeof(cases) / sizeof(cases[0])); i++) { int hash = find_hash(cases[i].algo); if (hash == -1) continue; ++tested; outlen = sizeof(digest); if((err = hmac_memory(hash, cases[i].key, cases[i].keylen, cases[i].data, cases[i].datalen, digest, &outlen)) != CRYPT_OK) { #if 0 printf("HMAC-%s test #%d\n", cases[i].algo, cases[i].num); #endif return err; } if(memcmp(digest, cases[i].digest, (size_t)hash_descriptor[hash].hashsize) != 0) { #if 0 unsigned int j; printf("\nHMAC-%s test #%d:\n", cases[i].algo, cases[i].num); printf( "Result: 0x"); for(j=0; j < hash_descriptor[hash].hashsize; j++) { printf("%2x ", digest[j]); } printf("\nCorrect: 0x"); for(j=0; j < hash_descriptor[hash].hashsize; j++) { printf("%2x ", cases[i].digest[j]); } printf("\n"); #endif failed++; //return CRYPT_ERROR; } else { /* printf("HMAC-%s test #%d: Passed\n", cases[i].algo, cases[i].num); */ } } if (failed != 0) { return CRYPT_FAIL_TESTVECTOR; } else if (tested == 0) { return CRYPT_NOP; } else { return CRYPT_OK; } #endif }
int pkcs_5_alg2(const unsigned char *password, unsigned long password_len, const unsigned char *salt, unsigned long salt_len, int iteration_count, int hash_idx, unsigned char *out, unsigned long *outlen) { int err, itts; ulong32 blkno; unsigned long stored, left, x, y; unsigned char *buf[2]; hmac_state *hmac; LTC_ARGCHK(password != NULL); LTC_ARGCHK(salt != NULL); LTC_ARGCHK(out != NULL); LTC_ARGCHK(outlen != NULL); /* test hash IDX */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } buf[0] = XMALLOC(MAXBLOCKSIZE * 2); hmac = XMALLOC(sizeof(hmac_state)); if (hmac == NULL || buf[0] == NULL) { if (hmac != NULL) { XFREE(hmac); } if (buf[0] != NULL) { XFREE(buf[0]); } return CRYPT_MEM; } /* buf[1] points to the second block of MAXBLOCKSIZE bytes */ buf[1] = buf[0] + MAXBLOCKSIZE; left = *outlen; blkno = 1; stored = 0; while (left != 0) { /* process block number blkno */ zeromem(buf[0], MAXBLOCKSIZE*2); /* store current block number and increment for next pass */ STORE32H(blkno, buf[1]); ++blkno; /* get PRF(P, S||int(blkno)) */ if ((err = hmac_init(hmac, hash_idx, password, password_len)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_process(hmac, salt, salt_len)) != CRYPT_OK) { goto LBL_ERR; } if ((err = hmac_process(hmac, buf[1], 4)) != CRYPT_OK) { goto LBL_ERR; } x = MAXBLOCKSIZE; if ((err = hmac_done(hmac, buf[0], &x)) != CRYPT_OK) { goto LBL_ERR; } /* now compute repeated and XOR it in buf[1] */ XMEMCPY(buf[1], buf[0], x); for (itts = 1; itts < iteration_count; ++itts) { if ((err = hmac_memory(hash_idx, password, password_len, buf[0], x, buf[0], &x)) != CRYPT_OK) { goto LBL_ERR; } for (y = 0; y < x; y++) { buf[1][y] ^= buf[0][y]; } } /* now emit upto x bytes of buf[1] to output */ for (y = 0; y < x && left != 0; ++y) { out[stored++] = buf[1][y]; --left; } } *outlen = stored; err = CRYPT_OK; LBL_ERR: #ifdef LTC_CLEAN_STACK zeromem(buf[0], MAXBLOCKSIZE*2); zeromem(hmac, sizeof(hmac_state)); #endif XFREE(hmac); XFREE(buf[0]); return err; }
int multi_test(void) { unsigned char key[32] = { 0 }; unsigned char buf[2][MAXBLOCKSIZE]; unsigned long len, len2; /* register algos */ register_hash(&sha256_desc); register_cipher(&aes_desc); /* HASH testing */ len = sizeof(buf[0]); hash_memory(find_hash("sha256"), (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL, 0); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #ifdef LTC_HMAC len = sizeof(buf[0]); hmac_memory(find_hash("sha256"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_OMAC len = sizeof(buf[0]); omac_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_PMAC len = sizeof(buf[0]); pmac_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_XCBC len = sizeof(buf[0]); xcbc_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); xcbc_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); xcbc_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); xcbc_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_F9 len = sizeof(buf[0]); f9_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); f9_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); f9_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); f9_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_PELICAN /* TODO: there is no pelican_memory_multi(..) */ #endif #ifdef LTC_POLY1305 len = sizeof(buf[0]); poly1305_memory(key, 32, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); poly1305_memory_multi(key, 32, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); poly1305_memory_multi(key, 32, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = sizeof(buf[0]); poly1305_memory_multi(key, 32, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_BLAKE2SMAC len = 32; blake2smac_memory(key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = 32; blake2smac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = 32; blake2smac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = 32; blake2smac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif #ifdef LTC_BLAKE2BMAC len = 64; blake2bmac_memory(key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = 64; blake2bmac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = 64; blake2bmac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } len2 = 64; blake2bmac_memory_multi(key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return CRYPT_FAIL_TESTVECTOR; } #endif return CRYPT_OK; }
/* IF YOU CALL THIS MULTIPLE TIMES WITH THE SAME KEY YOU MUST PROVIDE AN IV POINTER! */ int crypt_data(const unsigned char *data_in, unsigned char *data_out, size_t data_size, const unsigned char *data_mkey, size_t data_mkey_size, unsigned char *data_new_hmac, const unsigned char *data_chk_hmac, size_t data_hmac_size, unsigned char **IV_start, int mode) { if (mode != MODE_ENCRYPT && mode != MODE_DECRYPT) { fprintf(stderr, "crypt_data called with invalid mode %d\n", mode); return -1; } symmetric_CTR ctr; #ifdef _POSIX_MEMLOCK_RANGE if (mlock(&ctr, sizeof(ctr)) != 0) { fprintf(stderr, "WARNING: mlock failed at %s:%d - ", __FILE__, __LINE__); perror(""); } #endif int err; int ret = 0; /* return code */ unsigned char *IV; unsigned long IV_size = 16; int hash_idx = find_hash("sha256"); size_t data_ckey_size, data_hkey_size; data_ckey_size = data_hkey_size = data_mkey_size; unsigned char *subkeys = safe_malloc(data_ckey_size + data_hkey_size); #ifdef _POSIX_MEMLOCK_RANGE if (mlock(subkeys, data_ckey_size + data_hkey_size) != 0) { fprintf(stderr, "WARNING: mlock failed at %s:%d - ", __FILE__, __LINE__); perror(""); } #endif unsigned char *data_ckey = subkeys + 0; unsigned char *data_hkey = subkeys + data_ckey_size; pbkdf2(data_mkey, data_mkey_size, "H", 1, SUBKEY_ITER, hash_idx, data_hkey, &data_hkey_size); pbkdf2(data_mkey, data_mkey_size, "C", 1, SUBKEY_ITER, hash_idx, data_ckey, &data_ckey_size); if (IV_start == NULL || *IV_start == NULL) { IV = safe_malloc(IV_size); /* fprintf(stderr, "Initializing key-based IV\n"); */ /* This is at least as secure as starting with a zeroed IV */ pbkdf2(data_mkey, data_mkey_size, "I", 1, SUBKEY_ITER, hash_idx, IV, &IV_size); } if (IV_start != NULL) { if (*IV_start != NULL) { /* fprintf(stderr, "IV = *IV_start\n"); */ IV = *IV_start; } else { /* fprintf(stderr, "*IV_start = IV\n"); */ *IV_start = IV; } } if (mode == MODE_DECRYPT && data_chk_hmac != NULL) { if ((err = hmac_vrfymem(hash_idx, data_hkey, data_hkey_size, data_in, data_size, data_chk_hmac, (long unsigned int *)&data_hmac_size)) != CRYPT_OK) { crypt_data_return(THRCR_BADMAC); } } /* LTC_CTR_RFC3686 is needed to avoid reusing a counter value. */ if ((err = ctr_start(find_cipher("aes"), IV, data_ckey, data_ckey_size, 0, CTR_COUNTER_BIG_ENDIAN | LTC_CTR_RFC3686, &ctr)) != CRYPT_OK) { fprintf(stderr, "Error initializing cipher: %d\n", err); crypt_data_return(-1); } /* ctr_encrypt is used for both encryption and decryption */ if ((err = ctr_encrypt(data_in, data_out, data_size, &ctr)) != CRYPT_OK) { fprintf(stderr, "ctr_encrypt error: %s\n", error_to_string(err)); ctr_done(&ctr); /* done with cipher, clean up keys */ crypt_data_return(-1); } ctr_done(&ctr); /* done with cipher, clean up keys */ if (mode == MODE_ENCRYPT && data_new_hmac != NULL) { if ((err = hmac_memory(hash_idx, data_hkey, data_hkey_size, data_out, data_size, data_new_hmac, (long unsigned int *)&data_hmac_size)) != CRYPT_OK) { fprintf(stderr, "hmac error: %s\n", error_to_string(err)); crypt_data_return(-1); } } crypt_data_return: /* before actually returning, make sure key material isn't in memory */ MEMWIPE(&ctr, sizeof(ctr)); MEMWIPE(subkeys, data_ckey_size + data_hkey_size); #ifdef _POSIX_MEMLOCK_RANGE munlock(subkeys, data_ckey_size + data_hkey_size); #endif safe_free(subkeys); /* save the IV */ if (IV_start != NULL && *IV_start != NULL) { /* fprintf(stderr, "*IV_start = ctr.ctr\n"); */ ctr_getiv(*IV_start, &IV_size, &ctr); } else { safe_free(IV); } return ret; }
int hkdf_expand(int hash_idx, const unsigned char *info, unsigned long infolen, const unsigned char *in, unsigned long inlen, unsigned char *out, unsigned long outlen) { unsigned long hashsize; int err; unsigned char N; unsigned long Noutlen, outoff; unsigned char *T, *dat; unsigned long Tlen, datlen; /* make sure hash descriptor is valid */ if ((err = hash_is_valid(hash_idx)) != CRYPT_OK) { return err; } hashsize = hash_descriptor[hash_idx].hashsize; /* RFC5869 parameter restrictions */ if (inlen < hashsize || outlen > hashsize * 255) return CRYPT_INVALID_ARG; if (info == NULL && infolen != 0) return CRYPT_INVALID_ARG; LTC_ARGCHK(out != NULL); Tlen = hashsize + infolen + 1; T = XMALLOC(Tlen); /* Replace with static buffer? */ if (T == NULL) { return CRYPT_MEM; } if (info != NULL) { XMEMCPY(T + hashsize, info, infolen); } /* HMAC data T(1) doesn't include a previous hash value */ dat = T + hashsize; datlen = Tlen - hashsize; N = 0; outoff = 0; /* offset in out to write to */ while (1) { /* an exit condition breaks mid-loop */ Noutlen = MIN(hashsize, outlen - outoff); T[Tlen - 1] = ++N; if ((err = hmac_memory(hash_idx, in, inlen, dat, datlen, out + outoff, &Noutlen)) != CRYPT_OK) { zeromem(T, Tlen); XFREE(T); return err; } outoff += Noutlen; if (outoff >= outlen) /* loop exit condition */ break; /* All subsequent HMAC data T(N) DOES include the previous hash value */ XMEMCPY(T, out + hashsize * (N-1), hashsize); if (N == 1) { dat = T; datlen = Tlen; } } zeromem(T, Tlen); XFREE(T); return CRYPT_OK; }
int main(void) { unsigned char key[16], buf[2][MAXBLOCKSIZE]; unsigned long len, len2; /* register algos */ register_hash(&sha256_desc); register_cipher(&aes_desc); /* HASH testing */ len = sizeof(buf[0]); hash_memory(find_hash("sha256"), (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL, 0); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); hash_memory_multi(find_hash("sha256"), buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } /* LTC_HMAC */ len = sizeof(buf[0]); hmac_memory(find_hash("sha256"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); hmac_memory_multi(find_hash("sha256"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } /* LTC_OMAC */ len = sizeof(buf[0]); omac_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); omac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } /* PMAC */ len = sizeof(buf[0]); pmac_memory(find_cipher("aes"), key, 16, (unsigned char*)"hello", 5, buf[0], &len); len2 = sizeof(buf[0]); pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"hello", 5, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"he", 2UL, "llo", 3UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } len2 = sizeof(buf[0]); pmac_memory_multi(find_cipher("aes"), key, 16, buf[1], &len2, (unsigned char*)"h", 1UL, "e", 1UL, "l", 1UL, "l", 1UL, "o", 1UL, NULL); if (len != len2 || memcmp(buf[0], buf[1], len)) { printf("Failed: %d %lu %lu\n", __LINE__, len, len2); return EXIT_FAILURE; } printf("All passed\n"); return EXIT_SUCCESS; }