1//
2//  CommonHMac.c
3//  CommonCrypto
4//
5//  Created by Richard Murphy on 1/21/14.
6//  Copyright (c) 2014 Apple Inc. All rights reserved.
7//
8
9#include <stdio.h>
10#include "testbyteBuffer.h"
11#include "capabilities.h"
12#include "testmore.h"
13#include "testutil.h"
14#include <string.h>
15
16#include <CommonCrypto/CommonCryptor.h>
17#include <CommonCrypto/CommonDigest.h>
18#include <CommonCrypto/CommonHMAC.h>
19#include <CommonCrypto/CommonHMacSPI.h>
20#include <CommonCrypto/CommonKeyDerivationSPI.h>
21#include <CommonCrypto/CommonDigestSPI.h>
22
23
24typedef struct HMacVector_t {
25    char *keystr;
26    char *input;
27    char *md5str;
28    char *sha1str;
29    char *sha224str;
30    char *sha256str;
31    char *sha384str;
32    char *sha512str;
33} HMacVector;
34
35static HMacVector hmv[] = {
36    { // Test Case 1 http://www.faqs.org/rfcs/rfc4231.html MD5 derived
37        "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
38        "Hi There",
39        "5ccec34ea9656392457fa1ac27f08fbc",
40        "b617318655057264e28bc0b6fb378c8ef146be00",
41        "896fb1128abbdf196832107cd49df33f47b4b1169912ba4f53684b22",
42        "b0344c61d8db38535ca8afceaf0bf12b881dc200c9833da726e9376c2e32cff7",
43        "afd03944d84895626b0825f4ab46907f15f9dadbe4101ec682aa034c7cebc59cfaea9ea9076ede7f4af152e8b2fa9cb6",
44        "87aa7cdea5ef619d4ff0b4241a1d6cb02379f4e2ce4ec2787ad0b30545e17cdedaa833b7d6b8a702038b274eaea3f4e4be9d914eeb61f1702e696c203a126854",
45    },
46    { // Test Vector from http://www.faqs.org/rfcs/rfc2104.html - all but MD5 derived
47        "0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b0b",
48        "Hi There",
49        "9294727a3638bb1c13f48ef8158bfc9d",
50        "675b0b3a1b4ddf4e124872da6c2f632bfed957e9",
51        "4e841ce7a4ae83fbcf71e3cd64bfbf277f73a14680aae8c518ac7861",
52        "492ce020fe2534a5789dc3848806c78f4f6711397f08e7e7a12ca5a4483c8aa6",
53        "7afaa633e20d379b02395915fbc385ff8dc27dcd3885e1068ab942eeab52ec1f20ad382a92370d8b2e0ac8b83c4d53bf",
54        "7641c48a3b4aa8f887c07b3e83f96affb89c978fed8c96fcbbf4ad596eebfe496f9f16da6cd080ba393c6f365ad72b50d15c71bfb1d6b81f66a911786c6ce932",
55    },
56    { // Try this with a NULL key
57        NULL,
58        "Hi There",
59        "72c33c78cac0b7a581ac263a344ed01d",
60        "69536cc84eee5fe51c5b051aff8485f5c9ef0b58",
61        "da8f94de91d62154b55ea4e8d6eb133f6d553bcd1f1ba205b9488945",
62        "e48411262715c8370cd5e7bf8e82bef53bd53712d007f3429351843b77c7bb9b",
63        "da5393cef424a670d6db42c6ed6e7920779dfa4cbb98bf1c2e9c12ae10d10905d0c9e9d576c2a613be54b8daea246d4b",
64        "f7688a104326d36c1940f6d28d746c0661d383e0d14fe8a04649444777610f5dd9565a36846ab9e9e734cf380d3a070d8ef021b5f3a50c481710a464968e3419",
65    },
66    { // Same with a "" Key - Zero Length with string
67        "",
68        "Hi There",
69        "72c33c78cac0b7a581ac263a344ed01d",
70        "69536cc84eee5fe51c5b051aff8485f5c9ef0b58",
71        "da8f94de91d62154b55ea4e8d6eb133f6d553bcd1f1ba205b9488945",
72        "e48411262715c8370cd5e7bf8e82bef53bd53712d007f3429351843b77c7bb9b",
73        "da5393cef424a670d6db42c6ed6e7920779dfa4cbb98bf1c2e9c12ae10d10905d0c9e9d576c2a613be54b8daea246d4b",
74        "f7688a104326d36c1940f6d28d746c0661d383e0d14fe8a04649444777610f5dd9565a36846ab9e9e734cf380d3a070d8ef021b5f3a50c481710a464968e3419",
75    },
76
77};
78
79static size_t hmvLen = sizeof(hmv) / sizeof(HMacVector);
80
81
82
83static char * testString(char *format, CCDigestAlgorithm alg) {
84    static char thestring[80];
85    sprintf(thestring, format, digestName(alg));
86    return thestring;
87}
88
89static int testOriginalOneShotHMac(CCDigestAlgorithm alg, byteBuffer key, char *input, byteBuffer expected) {
90    CCHmacAlgorithm hmacAlg = digestID2HMacID(alg);
91    byteBuffer computedMD = mallocDigestByteBuffer(alg);
92    int status = 0;
93
94    CCHmac(hmacAlg, key->bytes, key->len, input, strlen(input), computedMD->bytes);
95    ok(status = expectedEqualsComputed(testString("Original OneShot HMac-%s", alg), expected, computedMD), "HMac is as expected");
96    free(computedMD);
97    return status;
98}
99
100static int testOriginalDiscreetHMac(CCDigestAlgorithm alg, byteBuffer key, char *input, byteBuffer expected) {
101    CCHmacAlgorithm hmacAlg = digestID2HMacID(alg);
102    byteBuffer computedMD = mallocDigestByteBuffer(alg);
103    CCHmacContext ctx;
104    int status = 0;
105
106    CCHmacInit(&ctx, hmacAlg, key->bytes, key->len);
107    CCHmacUpdate(&ctx, input, strlen(input));
108    CCHmacFinal(&ctx, computedMD->bytes);
109    ok(status = expectedEqualsComputed(testString("Original Discreet HMac-%s", alg), expected, computedMD), "HMac is as expected");
110    free(computedMD);
111    return status;
112}
113
114static int testNewOneShotHMac(CCDigestAlgorithm alg, byteBuffer key, char *input, byteBuffer expected) {
115    byteBuffer computedMD = mallocDigestByteBuffer(alg);
116    int status = 0;
117
118    CCHmacOneShot(alg, key->bytes, key->len, input, strlen(input), computedMD->bytes);
119    ok(status = expectedEqualsComputed(testString("New OneShot HMac-%s", alg), expected, computedMD), "HMac is as expected");
120    free(computedMD);
121    return status;
122}
123
124static int testNewDiscreetHMac(CCDigestAlgorithm alg, byteBuffer key, char *input, byteBuffer expected) {
125    byteBuffer computedMD = mallocDigestByteBuffer(alg);
126    byteBuffer computedMD2 = mallocDigestByteBuffer(alg);
127    int status = 0;
128
129    CCHmacContextRef ctx = CCHmacCreate(alg, key->bytes, key->len);
130    CCHmacContextRef ctx2 = CCHmacClone(ctx);
131    CCHmacUpdate(ctx, input, strlen(input));
132    CCHmacFinal(ctx, computedMD->bytes);
133    CCHmacDestroy(ctx);
134    CCHmacUpdate(ctx2, input, strlen(input));
135    CCHmacFinal(ctx2, computedMD2->bytes);
136    CCHmacDestroy(ctx2);
137    ok(status = expectedEqualsComputed(testString("New OneShot HMac-%s", alg), expected, computedMD), "HMac is as expected");
138    ok(status = expectedEqualsComputed(testString("New OneShot HMac-%s", alg), expected, computedMD2), "HMac is as expected");
139    free(computedMD);
140    free(computedMD2);
141    return status;
142}
143
144static int testAllHMacs(CCDigestAlgorithm alg, byteBuffer key, char *input, byteBuffer expected) {
145    int status = 0;
146
147    ok(status = testOriginalOneShotHMac(alg, key, input, expected), "Test Original One Shot version of HMac");
148    ok(status &= testOriginalDiscreetHMac(alg, key, input, expected), "Test Original Discreet version of HMac");
149    ok(status &= testNewOneShotHMac(alg, key, input, expected), "Test New One Shot version of HMac");
150    ok(status &= testNewDiscreetHMac(alg, key, input, expected), "Test New Discreet version of HMac");
151    return status;
152}
153
154static int testHMac(HMacVector *hv) {
155    byteBuffer key = hexStringToBytes(hv->keystr);
156    int status = 0;
157
158    byteBuffer expectedMD = hexStringToBytesIfNotNULL(hv->md5str);
159    ok(status = testAllHMacs(kCCDigestMD5, key, hv->input, expectedMD), "Testing all MD5 Implementations");
160    free(expectedMD);
161
162    expectedMD = hexStringToBytesIfNotNULL(hv->sha1str);
163    ok(status &= testAllHMacs(kCCDigestSHA1, key, hv->input, expectedMD), "Testing all SHA1 Implementations");
164    free(expectedMD);
165
166    expectedMD = hexStringToBytesIfNotNULL(hv->sha224str);
167    ok(status &= testAllHMacs(kCCDigestSHA224, key, hv->input, expectedMD), "Testing all SHA224 Implementations");
168    free(expectedMD);
169
170    expectedMD = hexStringToBytesIfNotNULL(hv->sha256str);
171    ok(status &= testAllHMacs(kCCDigestSHA256, key, hv->input, expectedMD), "Testing all SHA256 Implementations");
172    free(expectedMD);
173
174    expectedMD = hexStringToBytesIfNotNULL(hv->sha384str);
175    ok(status &= testAllHMacs(kCCDigestSHA384, key, hv->input, expectedMD), "Testing all SHA384 Implementations");
176    free(expectedMD);
177
178    expectedMD = hexStringToBytesIfNotNULL(hv->sha512str);
179    ok(status &= testAllHMacs(kCCDigestSHA512, key, hv->input, expectedMD), "Testing all SHA512 Implementations");
180    free(expectedMD);
181
182    return status;
183}
184
185static size_t testsPerVector = 3;
186
187int CommonHMac(int argc, char *const *argv) {
188	plan_tests((int) (hmvLen*testsPerVector));
189
190    for(size_t testcase = 0; testcase < hmvLen; testcase++) {
191        // diag("Test %lu\n", testcase + 1);
192        ok(testHMac(&hmv[testcase]), "Successful full test of HMAC Vector");
193    }
194    return 0;
195}
196
197