/ OSX / libsecurity_apple_csp / lib / DH_exchange.cpp
DH_exchange.cpp
  1  /*
  2   * Copyright (c) 2000-2002,2011-2012,2014 Apple 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  /*
 20   * DH_exchange.cp - Diffie-Hellman key exchange
 21   */
 22   
 23  #include "DH_exchange.h"
 24  #include <Security/cssmerr.h>
 25  #include "DH_utils.h"
 26  #include "DH_keys.h"
 27  #include <strings.h>
 28  #include <opensslUtils/opensslUtils.h>
 29  
 30  void DeriveKey_DH (
 31  	const Context &context,
 32  	const CssmData &Param,			// other's public key. may be empty
 33  	CSSM_DATA *keyData,				// mallocd by caller
 34  									// we fill in keyData->Length bytes
 35  	AppleCSPSession &session)
 36  {
 37  	bool mallocdPrivKey;
 38  	size_t privSize;
 39  	
 40  	/* private DH key from context - required */
 41  	DH *privKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_KEY,
 42  		CSSM_KEYCLASS_PRIVATE_KEY, CSSM_KEYUSE_DERIVE, mallocdPrivKey);
 43  	if(privKey == NULL) {
 44  		CssmError::throwMe(CSSMERR_CSP_MISSING_ATTR_KEY);
 45  	}
 46  	cspDhDebug("DeriveKey_DH, privKey %p", privKey);
 47  	privSize = DH_size(privKey);
 48  	if(privSize < keyData->Length) {
 49  		/* we've been asked for more bits than this key can generate */
 50  		CssmError::throwMe(CSSMERR_CSP_UNSUPPORTED_KEY_SIZE);
 51  	}
 52  	
 53  	/*
 54  	 * Public key ("their" key) can come from two places:
 55  	 * -- in the context as a CSSM_ATTRIBUTE_PUBLIC_KEY. This is how 
 56  	 *    public keys in X509 format must be used in this function
 57  	 * -- in the incoming Param, the raw unformatted (PKCS3) form 
 58  	 */
 59  	bool mallocdPubKey = false;
 60  	BIGNUM *pubKeyBn = NULL;
 61  	bool allocdPubKeyBn = false;
 62  	DH *pubKey = contextToDhKey(context, session, CSSM_ATTRIBUTE_PUBLIC_KEY,
 63  		CSSM_KEYCLASS_PUBLIC_KEY, CSSM_KEYUSE_DERIVE, mallocdPubKey);
 64  	if(pubKey != NULL) {
 65  		if(pubKey->pub_key == NULL) {
 66  			errorLog0("DeriveKey_DH: public key in context with no pub_key\n");
 67  			CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
 68  		}
 69  		pubKeyBn = pubKey->pub_key;
 70  		cspDhDebug("DeriveKey_DH, pubKey from context %p", pubKey);
 71  	}
 72  	else {
 73  		if((Param.Data == NULL) || (Param.Length == 0)) {
 74  			errorLog0("DeriveKey_DH: no pub_key, no Param\n");
 75  			CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
 76  		}
 77  		pubKeyBn = BN_bin2bn(Param.Data, (int)Param.Length, NULL);
 78  		if(pubKeyBn == NULL) {
 79  			CssmError::throwMe(CSSMERR_CSP_MEMORY_ERROR);
 80  		}
 81  		allocdPubKeyBn = true;
 82  		cspDhDebug("DeriveKey_DH, no pubKey in context");
 83  	}
 84  	unsigned char *buf = (unsigned char *)session.malloc(privSize);
 85  	int rtn = DH_compute_key(buf, pubKeyBn, privKey);
 86  	if(rtn > 0) {
 87  		/*
 88  		 * FIXME : I have not found a specification describing *which*
 89  		 * bytes of the value we just computed we are supposed to
 90  		 * use as the actual key bytes. We use the M.S. bytes.
 91  		 *
 92  		 * Note that due to modulo arithmetic, we may have gotten fewer
 93  		 * bytes than we asked for. If so, the caller will have
 94  		 * to deal with that if they really need privSize bytes.
 95  		 */
 96  		assert((uint32)rtn <= privSize);
 97  		CSSM_SIZE toMove = keyData->Length;
 98  		if((uint32)rtn < toMove) {
 99  			toMove = (uint32)rtn;
100  		}
101  		memmove(keyData->Data, buf, toMove);
102  		keyData->Length = toMove;
103  	}
104  	if(mallocdPrivKey) {
105  		DH_free(privKey);
106  	}
107  	if(mallocdPubKey) {
108  		DH_free(pubKey);
109  	}
110  	if(allocdPubKeyBn) {
111  		BN_free(pubKeyBn);
112  	}
113  	session.free(buf);
114  	if(rtn <= 0) {
115  		throwRsaDsa("DH_compute_key");
116  	}
117  }
118