1/* 2 * Copyright (c) 2000-2002 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/* 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 30void 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 119