2 * Copyright (c) 2000-2001 Apple Computer, Inc. All Rights Reserved.
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
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.
20 // pkcs_7_8.cpp - encopde/decode key blobs in PKCS7 and
26 #include "AppleCSPUtils.h"
27 #include <Security/threading.h>
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.
34 static Mutex snaccLock
;
36 // bring in a ton of snacc-related stuff
37 #include <Security/asn-incl.h>
38 #include <Security/sm_vdatypes.h>
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>
56 static void algAndModeToOid(
58 CSSM_ENCRYPT_MODE mode
,
59 AsnOid
&oid
) // to set
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
);
69 case CSSM_ALGMODE_CBCPadIV8
:
70 case CSSM_ALGMODE_CBC_IV8
:
71 oid
.ReSet(rc2_cbc_arc
);
74 oid
.ReSet(rc2_ecb_arc
);
82 if(mode
== CSSM_ALGMODE_CBCPadIV8
) {
83 oid
.ReSet(rc5_CBCPad_arc
);
86 oid
.ReSet(rc5CBC_arc
);
90 oid
.ReSet(desx_CBC_arc
);
93 oid
.ReSet(rsaEncryption_arc
); // from pkcs1oids.h
96 errorLog2("algAndModeToOid: Unknown alg %d mode %d\n", (int)alg
,
98 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
107 * EncryptedData ::= SEQUENCE {
108 * version INTEGER {edVer0(0)} (edVer0),
109 * encryptedContentInfo EncryptedContentInfo
112 * EncryptedContentInfo ::= SEQUENCE {
113 * contentType ContentType,
114 * contentEncryptionAlgorithm
115 * ContentEncryptionAlgorithmIdentifier,
117 * [0] IMPLICIT EncryptedContent OPTIONAL
120 * EncryptedContent ::= OCTET STRING
123 #define PKCS7_BUFSIZE 128 /* plus sizeof encryptedContent */
126 * Given a symmetric CssmKey in raw format, and its encrypted blob,
127 * cook up a PKCS-7 encoded blob.
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
)
140 EncryptedContentInfo1
*eci
;
141 AlgorithmIdentifier
*algId
;
143 StLock
<Mutex
> _(snaccLock
);
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
;
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.
157 algAndModeToOid(alg
, mode
, algId
->algorithm
);
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
);
164 // cook up an AsnBuf to stash the encoded blob in
165 bLen
= PKCS7_BUFSIZE
+ encryptedBlob
.Length
;
166 b
= (char *)allocator
.malloc(bLen
);
168 buf
.ResetInWriteRvsMode();
173 // malloc & copy back to encodedBlob
174 setUpCssmData(encodedBlob
, len
, allocator
);
175 memmove(encodedBlob
.Data
, buf
.DataPtr(), len
);
181 * Given a symmetric key in (encrypted, encoded) PKCS-7 format,
182 * obtain its encrypted key blob.
185 const CssmKey
&wrappedKey
, // for inferring format
186 CssmData
&decodedBlob
, // mallocd and RETURNED
187 CSSM_KEYBLOB_FORMAT
&format
, // RETURNED
188 CssmAllocator
&allocator
)
190 const CssmData
&encodedBlob
=
191 CssmData::overlay(wrappedKey
.KeyData
);
196 size_t len
= (size_t)encodedBlob
.Length
;
197 StLock
<Mutex
> _(snaccLock
);
199 buf
.InstallData((char *)encodedBlob
.Data
, len
);
202 EncryptedContentInfo1
*eci
;
204 ed
.BDec(buf
, len
, jbuf
);
207 if(i
!= EncryptedDataInt::edVer0
) {
208 errorLog1("cspDecodePkcs7: bad edDec.version (%d)\n", i
);
209 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
211 eci
= ed
.encryptedContentInfo
;
212 if(!(eci
->contentType
== encryptedData
)) {
213 errorLog0("cspDecodePkcs7: bad contentType\n");
214 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
217 /* ignore encryption alg (for now) */
219 /* eci->encryptedContent is decodedBlob */
220 setUpCssmData(decodedBlob
,
221 eci
->encryptedContent
->Len(),
223 memmove(decodedBlob
.Data
,
224 (char *)(*eci
->encryptedContent
),
225 eci
->encryptedContent
->Len());
228 errorLog1("cspDecodePkcs7: BDec threw %d\n", rtn
);
229 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
232 format
= inferFormat(wrappedKey
);
238 * EncryptedPrivateKeyInfo ::= SEQUENCE {
239 * encryptionAlgorithm AlgorithmIdentifier
240 * {{KeyEncryptionAlgorithms}},
241 * encryptedData EncryptedData
244 * EncryptedData ::= OCTET STRING
247 #define PKCS8_BUFSIZE 64 /* plus sizeof encryptedBlob */
250 * Given an asymmetric CssmKey in raw format, and its encrypted blob,
251 * cook up a PKCS-8 encoded blob.
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
)
263 EncryptedPrivateKeyInfo epki
;
265 StLock
<Mutex
> _(snaccLock
);
267 epki
.encryptionAlgorithm
= new AlgorithmIdentifier
;
268 algAndModeToOid(alg
, mode
, epki
.encryptionAlgorithm
->algorithm
);
269 epki
.encryptedKey
.Set((char *)encryptedBlob
.Data
, encryptedBlob
.Length
);
271 // cook up an AsnBuf to stash the encoded blob in
272 bLen
= PKCS8_BUFSIZE
+ encryptedBlob
.Length
;
273 b
= (char *)allocator
.malloc(bLen
);
275 buf
.ResetInWriteRvsMode();
278 len
= epki
.BEnc(buf
);
280 // malloc & copy back to encodedBlob
281 setUpCssmData(encodedBlob
, len
, allocator
);
282 memmove(encodedBlob
.Data
, buf
.DataPtr(), len
);
287 * Given a a private key in (encrypted, encoded) PKCS-8 format,
288 * obtain its encrypted key blob.
291 const CssmKey
&wrappedKey
, // for inferring format
292 CssmData
&decodedBlob
, // mallocd and RETURNED
293 CSSM_KEYBLOB_FORMAT
&format
, // RETURNED
294 CssmAllocator
&allocator
)
296 const CssmData
&encodedBlob
=
297 CssmData::overlay(wrappedKey
.KeyData
);
302 size_t len
= (size_t)encodedBlob
.Length
;
303 StLock
<Mutex
> _(snaccLock
);
305 buf
.InstallData((char *)encodedBlob
.Data
, len
);
307 EncryptedPrivateKeyInfo epki
;
309 epki
.BDec(buf
, len
, jbuf
);
311 /* skip algorithm - just snag encryptedKey */
312 len
= epki
.encryptedKey
.Len();
313 setUpCssmData(decodedBlob
, len
, allocator
);
314 memmove(decodedBlob
.Data
,
315 (char *)(epki
.encryptedKey
),
319 errorLog1("cspDecodePkcs8: BDec threw %d\n", rtn
);
320 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
323 format
= inferFormat(wrappedKey
);