1/*
2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
3 *
4 * The contents of this file constitute Original Code as defined in and are
5 * subject to the Apple Public Source License Version 1.2 (the 'License').
6 * You may not use this file except in compliance with the License. Please obtain
7 * a copy of the License at http://www.apple.com/publicsource and read it before
8 * using this file.
9 *
10 * This Original Code and all software distributed under the License are
11 * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER EXPRESS
12 * OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES, INCLUDING WITHOUT
13 * LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR
14 * PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT. Please see the License for the
15 * specific language governing rights and limitations under the License.
16 */
17
18/*
19 * MacContext.cpp - AppleCSPContext for HMACSHA1
20 */
21
22#include "MacContext.h"
23#include <HMACSHA1.h>
24#include <Security/cssmerr.h>
25#include <CommonCrypto/CommonDigest.h>	/* for digest sizes */
26#ifdef	CRYPTKIT_CSP_ENABLE
27#include <security_cryptkit/HmacSha1Legacy.h>
28#endif	/* CRYPTKIT_CSP_ENABLE */
29
30MacContext::~MacContext()
31{
32	memset(&hmacCtx, 0, sizeof(hmacCtx));
33}
34
35/* called out from CSPFullPluginSession....
36 * both generate and verify */
37void MacContext::init(const Context &context, bool isSigning)
38{
39	CCHmacAlgorithm ccAlg;
40
41	/* obtain key from context */
42	CSSM_SIZE	keyLen;
43	uint8 		*keyData 	= NULL;
44
45	symmetricKeyBits(context, session(), mAlg,
46		isSigning ? CSSM_KEYUSE_SIGN : CSSM_KEYUSE_VERIFY,
47		keyData, keyLen);
48	uint32 minKey = 0;
49	switch(mAlg) {
50		case CSSM_ALGID_SHA1HMAC:
51			minKey = HMAC_SHA_MIN_KEY_SIZE;
52			mDigestSize = CC_SHA1_DIGEST_LENGTH;
53			ccAlg = kCCHmacAlgSHA1;
54			break;
55		case CSSM_ALGID_MD5HMAC:
56			minKey = HMAC_MD5_MIN_KEY_SIZE;
57			mDigestSize = CC_MD5_DIGEST_LENGTH;
58			ccAlg = kCCHmacAlgMD5;
59			break;
60		default:
61			assert(0);			// factory should not have called us
62			CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
63	}
64	if((keyLen < minKey) || (keyLen > HMAC_MAX_KEY_SIZE)) {
65		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
66	}
67	CCHmacInit(&hmacCtx, ccAlg, keyData, keyLen);
68}
69
70void MacContext::update(const CssmData &data)
71{
72	CCHmacUpdate(&hmacCtx, data.data(), data.length());
73}
74
75/* generate only */
76void MacContext::final(CssmData &out)
77{
78	if(out.length() < mDigestSize) {
79		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
80	}
81	CCHmacFinal(&hmacCtx, out.data());
82	out.Length = mDigestSize;
83}
84
85/* verify only */
86#define MAX_DIGEST_SIZE		CC_SHA1_DIGEST_LENGTH
87
88void MacContext::final(const CssmData &in)
89{
90	unsigned char mac[MAX_DIGEST_SIZE];
91
92	CCHmacFinal(&hmacCtx, mac);
93	if(memcmp(mac, in.data(), mDigestSize)) {
94		CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
95	}
96}
97
98size_t MacContext::outputSize(bool final, size_t inSize)
99{
100	return mDigestSize;
101}
102
103#ifdef 	CRYPTKIT_CSP_ENABLE
104
105MacLegacyContext::~MacLegacyContext()
106{
107	if(mHmac) {
108		hmacLegacyFree(mHmac);
109		mHmac = NULL;
110	}
111}
112
113/* called out from CSPFullPluginSession....
114 * both generate and verify: */
115void MacLegacyContext::init(const Context &context, bool isSigning)
116{
117	if(mHmac == NULL) {
118		mHmac = hmacLegacyAlloc();
119		if(mHmac == NULL) {
120			CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
121		}
122	}
123
124	/* obtain key from context */
125	CSSM_SIZE	keyLen;
126	uint8 		*keyData 	= NULL;
127
128	/* FIXME - this may require a different key alg */
129	symmetricKeyBits(context, session(), CSSM_ALGID_SHA1HMAC,
130		isSigning ? CSSM_KEYUSE_SIGN : CSSM_KEYUSE_VERIFY,
131		keyData, keyLen);
132	if((keyLen < HMAC_SHA_MIN_KEY_SIZE) || (keyLen > HMAC_MAX_KEY_SIZE)) {
133		CssmError::throwMe(CSSMERR_CSP_INVALID_ATTR_KEY);
134	}
135
136	OSStatus ortn = hmacLegacyInit(mHmac, keyData, (UInt32)keyLen);
137	if(ortn) {
138		MacOSError::throwMe(ortn);
139	}
140}
141
142void MacLegacyContext::update(const CssmData &data)
143{
144	OSStatus ortn = hmacLegacyUpdate(mHmac,
145		data.data(),
146		(UInt32)data.length());
147	if(ortn) {
148		MacOSError::throwMe(ortn);
149	}
150}
151
152/* generate only */
153void MacLegacyContext::final(CssmData &out)
154{
155	if(out.length() < kHMACSHA1DigestSize) {
156		CssmError::throwMe(CSSMERR_CSP_OUTPUT_LENGTH_ERROR);
157	}
158	hmacLegacyFinal(mHmac, out.data());
159}
160
161/* verify only */
162void MacLegacyContext::final(const CssmData &in)
163{
164	unsigned char mac[kHMACSHA1DigestSize];
165	hmacLegacyFinal(mHmac, mac);
166	if(memcmp(mac, in.data(), kHMACSHA1DigestSize)) {
167		CssmError::throwMe(CSSMERR_CSP_VERIFY_FAILED);
168	}
169}
170
171size_t MacLegacyContext::outputSize(bool final, size_t inSize)
172{
173	return kHMACSHA1DigestSize;
174}
175
176#endif	/* CRYPTKIT_CSP_ENABLE */
177