]> git.saurik.com Git - apple/security.git/blob - OSX/libsecurity_apple_csp/lib/DH_utils.cpp
Security-57337.40.85.tar.gz
[apple/security.git] / OSX / libsecurity_apple_csp / lib / 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.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 */
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