]> git.saurik.com Git - apple/security.git/blob - AppleCSP/AppleCSP/pkcs_7_8.cpp
8d54cd556f1741910b6cf999e7053570cc4b0f0c
[apple/security.git] / AppleCSP / AppleCSP / pkcs_7_8.cpp
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 // pkcs_7_8.cpp - encopde/decode key blobs in PKCS7 and
21 // PKCS8 format.
22 //
23
24
25 #include "pkcs_7_8.h"
26 #include "AppleCSPUtils.h"
27 #include <Security/threading.h>
28
29 /*
30 * NOTE: snacc-generated code is believed to be not thread safe. Thus we
31 * use the Mutex snaccLock to single-thread access to snacc-generated code.
32 */
33
34 static Mutex snaccLock;
35
36 // bring in a ton of snacc-related stuff
37 #include <Security/asn-incl.h>
38 #include <Security/sm_vdatypes.h>
39
40 // snacc-generated - snacc really should place these in pkcs[78].h
41 #include <Security/sm_x501ud.h>
42 #include <Security/sm_x411ub.h>
43 #include <Security/sm_x411mtsas.h>
44 #include <Security/sm_x501if.h>
45 #include <Security/sm_x520sa.h>
46 #include <Security/sm_x509cmn.h>
47 #include <Security/sm_x509af.h>
48 #include <Security/sm_x509ce.h>
49 #include <Security/pkcs1oids.h>
50 #include <Security/pkcs9oids.h>
51 #include <Security/sm_cms.h>
52 #include <Security/sm_ess.h>
53 #include <Security/pkcs7.h>
54 #include <Security/pkcs8.h>
55
56 static void algAndModeToOid(
57 CSSM_ALGORITHMS alg,
58 CSSM_ENCRYPT_MODE mode,
59 AsnOid &oid) // to set
60 {
61 switch(alg) {
62 case CSSM_ALGID_DES:
63 /* FIXME - plain old 56-bit DES doesn't have an OID! */
64 case CSSM_ALGID_3DES_3KEY_EDE:
65 oid.ReSet(des_ede3_cbc_arc);
66 break;
67 case CSSM_ALGID_RC2:
68 switch(mode) {
69 case CSSM_ALGMODE_CBCPadIV8:
70 case CSSM_ALGMODE_CBC_IV8:
71 oid.ReSet(rc2_cbc_arc);
72 break;
73 default:
74 oid.ReSet(rc2_ecb_arc);
75 break;
76 }
77 break;
78 case CSSM_ALGID_RC4:
79 oid.ReSet(rc4_arc);
80 break;
81 case CSSM_ALGID_RC5:
82 if(mode == CSSM_ALGMODE_CBCPadIV8) {
83 oid.ReSet(rc5_CBCPad_arc);
84 }
85 else {
86 oid.ReSet(rc5CBC_arc);
87 }
88 break;
89 case CSSM_ALGID_DESX:
90 oid.ReSet(desx_CBC_arc);
91 break;
92 case CSSM_ALGID_RSA:
93 oid.ReSet(rsaEncryption_arc); // from pkcs1oids.h
94 break;
95 default:
96 errorLog2("algAndModeToOid: Unknown alg %d mode %d\n", (int)alg,
97 (int)mode);
98 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM);
99 }
100 return;
101 }
102
103
104 /*
105 * PKCS 7 format:
106 *
107 * EncryptedData ::= SEQUENCE {
108 * version INTEGER {edVer0(0)} (edVer0),
109 * encryptedContentInfo EncryptedContentInfo
110 * }
111 *
112 * EncryptedContentInfo ::= SEQUENCE {
113 * contentType ContentType,
114 * contentEncryptionAlgorithm
115 * ContentEncryptionAlgorithmIdentifier,
116 * encryptedContent
117 * [0] IMPLICIT EncryptedContent OPTIONAL
118 * }
119 *
120 * EncryptedContent ::= OCTET STRING
121 */
122
123 #define PKCS7_BUFSIZE 128 /* plus sizeof encryptedContent */
124
125 /*
126 * Given a symmetric CssmKey in raw format, and its encrypted blob,
127 * cook up a PKCS-7 encoded blob.
128 */
129 void cspEncodePkcs7(
130 CSSM_ALGORITHMS alg, // encryption alg, used by PKCS7
131 CSSM_ENCRYPT_MODE mode, // ditto
132 const CssmData &encryptedBlob,
133 CssmData &encodedBlob, // mallocd and RETURNED
134 CssmAllocator &allocator)
135 {
136 AsnBuf buf;
137 char *b;
138 unsigned bLen;
139 EncryptedData1 ed;
140 EncryptedContentInfo1 *eci;
141 AlgorithmIdentifier *algId;
142 AsnLen len;
143 StLock<Mutex> _(snaccLock);
144
145 // init some values
146 ed.version.Set(EncryptedDataInt::edVer0);
147 eci = ed.encryptedContentInfo = new EncryptedContentInfo1;
148 eci->contentType = encryptedData; // OID from pkcs7.h
149 algId = eci->contentEncryptionAlgorithm = new AlgorithmIdentifier;
150
151 /*
152 * select an AsnOid based in key algorithm and mode.
153 * Note we support more alg/mode combos that there are
154 * assigned oids; no big deal - currently we don't even
155 * parse the OID on decode anyway.
156 */
157 algAndModeToOid(alg, mode, algId->algorithm);
158
159 // unlike pkcs8, this one is a pointer - it gets deleted by
160 // EncryptedContentInfo1's destructor
161 eci->encryptedContent = new AsnOcts(
162 (char *)encryptedBlob.Data, (size_t)encryptedBlob.Length);
163
164 // cook up an AsnBuf to stash the encoded blob in
165 bLen = PKCS7_BUFSIZE + encryptedBlob.Length;
166 b = (char *)allocator.malloc(bLen);
167 buf.Init(b, bLen);
168 buf.ResetInWriteRvsMode();
169
170 // pkcs7 encode
171 len = ed.BEnc(buf);
172
173 // malloc & copy back to encodedBlob
174 setUpCssmData(encodedBlob, len, allocator);
175 memmove(encodedBlob.Data, buf.DataPtr(), len);
176 allocator.free(b);
177 }
178
179
180 /*
181 * Given a symmetric key in (encrypted, encoded) PKCS-7 format,
182 * obtain its encrypted key blob.
183 */
184 void cspDecodePkcs7(
185 const CssmKey &wrappedKey, // for inferring format
186 CssmData &decodedBlob, // mallocd and RETURNED
187 CSSM_KEYBLOB_FORMAT &format, // RETURNED
188 CssmAllocator &allocator)
189 {
190 const CssmData &encodedBlob =
191 CssmData::overlay(wrappedKey.KeyData);
192 ENV_TYPE jbuf;
193 EncryptedData1 ed;
194 int rtn;
195 AsnBuf buf;
196 size_t len = (size_t)encodedBlob.Length;
197 StLock<Mutex> _(snaccLock);
198
199 buf.InstallData((char *)encodedBlob.Data, len);
200 try {
201 int i;
202 EncryptedContentInfo1 *eci;
203
204 ed.BDec(buf, len, jbuf);
205
206 i = ed.version;
207 if(i != EncryptedDataInt::edVer0) {
208 errorLog1("cspDecodePkcs7: bad edDec.version (%d)\n", i);
209 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
210 }
211 eci = ed.encryptedContentInfo;
212 if(!(eci->contentType == encryptedData)) {
213 errorLog0("cspDecodePkcs7: bad contentType\n");
214 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
215 }
216
217 /* ignore encryption alg (for now) */
218
219 /* eci->encryptedContent is decodedBlob */
220 setUpCssmData(decodedBlob,
221 eci->encryptedContent->Len(),
222 allocator);
223 memmove(decodedBlob.Data,
224 (char *)(*eci->encryptedContent),
225 eci->encryptedContent->Len());
226 }
227 catch(...) {
228 errorLog1("cspDecodePkcs7: BDec threw %d\n", rtn);
229 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
230 }
231
232 format = inferFormat(wrappedKey);
233 }
234
235 /*
236 * PKCS-8 format
237 *
238 * EncryptedPrivateKeyInfo ::= SEQUENCE {
239 * encryptionAlgorithm AlgorithmIdentifier
240 * {{KeyEncryptionAlgorithms}},
241 * encryptedData EncryptedData
242 * }
243 *
244 * EncryptedData ::= OCTET STRING
245 */
246
247 #define PKCS8_BUFSIZE 64 /* plus sizeof encryptedBlob */
248
249 /*
250 * Given an asymmetric CssmKey in raw format, and its encrypted blob,
251 * cook up a PKCS-8 encoded blob.
252 */
253 void cspEncodePkcs8(
254 CSSM_ALGORITHMS alg, // encryption alg, used by PKCS8
255 CSSM_ENCRYPT_MODE mode, // ditto
256 const CssmData &encryptedBlob,
257 CssmData &encodedBlob, // mallocd and RETURNED
258 CssmAllocator &allocator)
259 {
260 AsnBuf buf;
261 char *b;
262 unsigned bLen;
263 EncryptedPrivateKeyInfo epki;
264 AsnLen len;
265 StLock<Mutex> _(snaccLock);
266
267 epki.encryptionAlgorithm = new AlgorithmIdentifier;
268 algAndModeToOid(alg, mode, epki.encryptionAlgorithm->algorithm);
269 epki.encryptedKey.Set((char *)encryptedBlob.Data, encryptedBlob.Length);
270
271 // cook up an AsnBuf to stash the encoded blob in
272 bLen = PKCS8_BUFSIZE + encryptedBlob.Length;
273 b = (char *)allocator.malloc(bLen);
274 buf.Init(b, bLen);
275 buf.ResetInWriteRvsMode();
276
277 // pkcs8 encode
278 len = epki.BEnc(buf);
279
280 // malloc & copy back to encodedBlob
281 setUpCssmData(encodedBlob, len, allocator);
282 memmove(encodedBlob.Data, buf.DataPtr(), len);
283 allocator.free(b);
284 }
285
286 /*
287 * Given a a private key in (encrypted, encoded) PKCS-8 format,
288 * obtain its encrypted key blob.
289 */
290 void cspDecodePkcs8(
291 const CssmKey &wrappedKey, // for inferring format
292 CssmData &decodedBlob, // mallocd and RETURNED
293 CSSM_KEYBLOB_FORMAT &format, // RETURNED
294 CssmAllocator &allocator)
295 {
296 const CssmData &encodedBlob =
297 CssmData::overlay(wrappedKey.KeyData);
298 ENV_TYPE jbuf;
299 EncryptedData1 ed;
300 int rtn;
301 AsnBuf buf;
302 size_t len = (size_t)encodedBlob.Length;
303 StLock<Mutex> _(snaccLock);
304
305 buf.InstallData((char *)encodedBlob.Data, len);
306 try {
307 EncryptedPrivateKeyInfo epki;
308
309 epki.BDec(buf, len, jbuf);
310
311 /* skip algorithm - just snag encryptedKey */
312 len = epki.encryptedKey.Len();
313 setUpCssmData(decodedBlob, len, allocator);
314 memmove(decodedBlob.Data,
315 (char *)(epki.encryptedKey),
316 len);
317 }
318 catch(...) {
319 errorLog1("cspDecodePkcs8: BDec threw %d\n", rtn);
320 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY);
321 }
322
323 format = inferFormat(wrappedKey);
324 }