/ OSX / libsecurity_apple_csp / lib / DH_utils.cpp
DH_utils.cpp
  1  /*
  2   * Copyright (c) 2000-2001,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_utils.cpp
 21   */
 22  
 23  #include "DH_utils.h"
 24  #include "DH_keys.h"
 25  #include <opensslUtils/opensslAsn1.h>
 26  #include <security_utilities/logging.h>
 27  #include <security_utilities/debugging.h>
 28  #include <opensslUtils/opensslUtils.h>
 29  #include <openssl/bn_legacy.h>
 30  #include <openssl/dh_legacy.h>
 31  #include <openssl/opensslerr.h>
 32  
 33  #define dhMiscDebug(args...)	secinfo("dhMisc", ## args)
 34  
 35  /* 
 36   * Given a Context:
 37   * -- obtain CSSM key with specified attr (there must only be one)
 38   * -- validate keyClass per caller's specification
 39   * -- validate keyUsage
 40   * -- convert to DH *, allocating the DH key if necessary
 41   */
 42  DH *contextToDhKey(
 43  	const Context		&context,
 44  	AppleCSPSession 	&session,
 45  	CSSM_ATTRIBUTE_TYPE	attr,		  // CSSM_ATTRIBUTE_KEY for private key
 46  									  // CSSM_ATTRIBUTE_PUBLIC_KEY for public key
 47  	CSSM_KEYCLASS		keyClass,	  // CSSM_KEYCLASS_{PUBLIC,PRIVATE}_KEY	
 48  	CSSM_KEYUSE			usage,		  // CSSM_KEYUSE_ENCRYPT, CSSM_KEYUSE_SIGN, etc.
 49  	bool				&mallocdKey)  // RETURNED
 50  {
 51      CssmKey *cssmKey = context.get<CssmKey>(attr);
 52  	if(cssmKey == NULL) {
 53  		return NULL;
 54  	}
 55  	const CSSM_KEYHEADER &hdr = cssmKey->KeyHeader;
 56  	if(hdr.AlgorithmId != CSSM_ALGID_DH) {
 57  		CssmError::throwMe(CSSMERR_CSP_ALGID_MISMATCH);
 58  	}
 59  	if(hdr.KeyClass != keyClass) {
 60  		CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
 61  	}
 62  	cspValidateIntendedKeyUsage(&hdr, usage);
 63  	cspVerifyKeyTimes(hdr);
 64  	return cssmKeyToDh(*cssmKey, session, mallocdKey);
 65  }
 66  
 67  /* 
 68   * Convert a CssmKey to an DH * key. May result in the 
 69   * creation of a new DH (when cssmKey is a raw key); allocdKey is true 
 70   * in that case in which case the caller generally has to free the allocd key).
 71   */
 72  DH *cssmKeyToDh(
 73  	const CssmKey	&cssmKey,
 74  	AppleCSPSession	&session,
 75  	bool			&allocdKey)		// RETURNED
 76  {
 77  	DH *dhKey = NULL;
 78  	allocdKey = false;
 79  	
 80  	const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
 81  	if(hdr->AlgorithmId != CSSM_ALGID_DH) {
 82  		// someone else's key (should never happen)
 83  		CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
 84  	}
 85  	switch(hdr->BlobType) {
 86  		case CSSM_KEYBLOB_RAW:
 87  			dhKey = rawCssmKeyToDh(cssmKey);
 88  			cspDhDebug("cssmKeyToDh, raw, dhKey %p", dhKey);
 89  			allocdKey = true;
 90  			break;
 91  		case CSSM_KEYBLOB_REFERENCE:
 92  		{
 93  			BinaryKey &binKey = session.lookupRefKey(cssmKey);
 94  			DHBinaryKey *dhBinKey = dynamic_cast<DHBinaryKey *>(&binKey);
 95  			/* this cast failing means that this is some other
 96  			 * kind of binary key */
 97  			if(dhBinKey == NULL) {
 98  				CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
 99  			}
100  			assert(dhBinKey->mDhKey != NULL);
101  			dhKey = dhBinKey->mDhKey;
102  			cspDhDebug("cssmKeyToDh, ref, dhKey %p", dhKey);
103  			break;
104  		}
105  		default:
106  			CssmError::throwMe(CSSMERR_CSP_KEY_BLOB_TYPE_INCORRECT);
107  	}
108  	return dhKey;
109  }
110  
111  /* 
112   * Convert a raw CssmKey to a newly alloc'd DH key.
113   */
114  DH *rawCssmKeyToDh(
115  	const CssmKey	&cssmKey)
116  {
117  	const CSSM_KEYHEADER *hdr = &cssmKey.KeyHeader;
118  	bool isPub = false;
119  	
120  	if(hdr->AlgorithmId != CSSM_ALGID_DH) {
121  		// someone else's key (should never happen)
122  		CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
123  	}
124  	assert(hdr->BlobType == CSSM_KEYBLOB_RAW);
125  	/* validate and figure out what we're dealing with */
126  	switch(hdr->KeyClass) {
127  		case CSSM_KEYCLASS_PUBLIC_KEY:
128  			switch(hdr->Format) {
129  				case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:	
130  				case CSSM_KEYBLOB_RAW_FORMAT_X509:
131  					break;
132  				/* openssh real soon now */
133  				case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
134  				default:
135  					CssmError::throwMe(
136  						CSSMERR_CSP_INVALID_ATTR_PUBLIC_KEY_FORMAT);
137  			}
138  			isPub = true;
139  			break;
140  		case CSSM_KEYCLASS_PRIVATE_KEY:
141  			switch(hdr->Format) {
142  				case CSSM_KEYBLOB_RAW_FORMAT_PKCS3:	// default
143  				case CSSM_KEYBLOB_RAW_FORMAT_PKCS8:	// SMIME style
144  					break;
145  				/* openssh real soon now */
146  				case CSSM_KEYBLOB_RAW_FORMAT_OPENSSH:
147  				default:
148  					CssmError::throwMe(
149  						CSSMERR_CSP_INVALID_ATTR_PRIVATE_KEY_FORMAT);
150  			}
151  			isPub = false;
152  			break;
153  		default:
154  			CssmError::throwMe(CSSMERR_CSP_INVALID_KEY_CLASS);
155  	}
156  	
157  	CSSM_RETURN crtn;
158  
159  	DH *dhKey = DH_new();
160  	if(dhKey == NULL) {
161  		crtn = CSSMERR_CSP_MEMORY_ERROR;
162  	}
163      else
164      {
165          if(isPub) {
166              crtn = DHPublicKeyDecode(dhKey, hdr->Format,
167                  cssmKey.KeyData.Data, (unsigned)cssmKey.KeyData.Length);
168          }
169          else {
170              crtn = DHPrivateKeyDecode(dhKey, hdr->Format,
171                  cssmKey.KeyData.Data, (unsigned)cssmKey.KeyData.Length);
172          }
173      }
174      
175  	if(crtn) {
176          if (dhKey != NULL) {
177              DH_free(dhKey);
178          }
179          
180          CssmError::throwMe(crtn);
181  	}
182  	cspDhDebug("rawCssmKeyToDh, dhKey %p", dhKey);
183  	return dhKey;
184  }
185