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/* 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.h> 30#include <openssl/dh.h> 31#include <openssl/err.h> 32 33#define dhMiscDebug(args...) secdebug("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 */ 42DH *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 */ 72DH *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 */ 114DH *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 186