2 * Copyright (c) 2000-2001,2011,2014 Apple 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 // pkcs8.cpp - PKCS8 key wrap/unwrap support.
25 #include "AppleCSPUtils.h"
26 #include "AppleCSPKeys.h"
27 #include <Security/keyTemplates.h>
28 #include <security_asn1/SecNssCoder.h>
29 #include <security_asn1/nssUtils.h>
30 #include "AppleCSPSession.h"
31 #include <Security/cssmapple.h>
34 * Given a key in PKCS8 format, fill in the following
37 * CSSM_KEYBLOB_FORMAT Format
38 * CSSM_ALGORITHMS AlgorithmId
39 * uint32 LogicalKeySizeInBits
41 void AppleCSPSession::pkcs8InferKeyHeader(
45 * Incoming key blob is a PrivateKeyInfo. Take it apart
46 * to get its algorithm info, from which we infer other
49 NSS_PrivateKeyInfo privKeyInfo
;
51 CSSM_DATA
&keyData
= key
.KeyData
;
53 memset(&privKeyInfo
, 0, sizeof(privKeyInfo
));
54 if(coder
.decodeItem(keyData
, kSecAsn1PrivateKeyInfoTemplate
,
56 errorLog0("pkcs8InferKeyHeader decode error\n");
57 CssmError::throwMe(CSSMERR_CSP_INVALID_KEY
);
60 CSSM_KEYHEADER
&hdr
= key
.KeyHeader
;
61 if(!cssmOidToAlg(&privKeyInfo
.algorithm
.algorithm
,
63 errorLog0("pkcs8InferKeyHeader unknown algorithm\n");
64 CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM
);
67 switch(hdr
.AlgorithmId
) {
69 case CSSM_ALGID_ECDSA
:
70 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
74 * Try openssl style first, though our default when
77 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
81 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
86 * Find someone who knows about this key and ask them the
87 * key size. infoProvider() throws if no provider found.
89 CSSM_KEY_SIZE keySize
;
91 unique_ptr
<CSPKeyInfoProvider
> provider(infoProvider(key
));
92 provider
->QueryKeySizeInBits(keySize
);
94 catch(const CssmError
&cerror
) {
96 * Special case: DSA private keys keys can be in two forms - FIPS186
97 * (for legacy implementations) and PKCS8 (for openssl). We're wired to
98 * *generate* FIPS186 blobs by default in pkcs8RawKeyFormat(), but to
99 * decode openssl-generated DSA private keys in wrapped FIPS186 format
100 * we have to try both.
102 if((cerror
.error
== CSSMERR_CSP_INVALID_KEY
) &&
103 (hdr
.AlgorithmId
== CSSM_ALGID_DSA
)) {
104 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
106 unique_ptr
<CSPKeyInfoProvider
> provider(infoProvider(key
));
107 provider
->QueryKeySizeInBits(keySize
);
115 /* other error, give up */
120 /* other (non-CSSM) error, give up */
123 hdr
.LogicalKeySizeInBits
= keySize
.LogicalKeySizeInBits
;
127 * When doing a PKCS8 wrap operation on a reference key, this
128 * is used to infer the blob type to obtain before the encryption.
129 * App can override this with a
130 * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT
133 CSSM_KEYBLOB_FORMAT
pkcs8RawKeyFormat(
134 CSSM_ALGORITHMS keyAlg
)
138 case CSSM_ALGID_ECDSA
:
139 return CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
141 return CSSM_KEYBLOB_RAW_FORMAT_FIPS186
;
144 return CSSM_KEYBLOB_RAW_FORMAT_NONE
;
149 * When doing a OPENSSL style wrap operation on a reference key, this
150 * is used to infer the blob type to obtain before the encryption.
151 * App can override this with a
152 * CSSM_ATTRIBUTE_{PRIVATE,PUBLIC,SESSION}_KEY_FORMAT
155 CSSM_KEYBLOB_FORMAT
opensslRawKeyFormat(
156 CSSM_ALGORITHMS keyAlg
)
160 return CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
162 return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
;
163 case CSSM_ALGID_ECDSA
:
164 return CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
167 return CSSM_KEYBLOB_RAW_FORMAT_NONE
;
172 * Given a key in some kind of openssl format (just subsequent to decryption
173 * during an unwrap), fill in the following header fields:
175 * CSSM_KEYBLOB_FORMAT Format
176 * uint32 LogicalKeySizeInBits
178 void AppleCSPSession::opensslInferKeyHeader(
181 CSSM_KEYHEADER
&hdr
= key
.KeyHeader
;
182 switch(hdr
.AlgorithmId
) {
184 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS1
;
187 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_OPENSSL
;
189 case CSSM_ALGID_ECDSA
:
190 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_PKCS8
;
194 hdr
.Format
= CSSM_KEYBLOB_RAW_FORMAT_NONE
;
198 /* now figure out the key size by finding a provider for this key */
199 CSSM_KEY_SIZE keySize
;
201 unique_ptr
<CSPKeyInfoProvider
> provider(infoProvider(key
));
202 provider
->QueryKeySizeInBits(keySize
);
205 /* no recovery possible */
208 hdr
.LogicalKeySizeInBits
= keySize
.LogicalKeySizeInBits
;