]>
Commit | Line | Data |
---|---|---|
b1ab9ed8 A |
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 | // pkcs8.cpp - PKCS8 key wrap/unwrap support. | |
21 | // | |
22 | ||
23 | ||
24 | #include "pkcs8.h" | |
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> | |
32 | ||
33 | /* | |
34 | * Given a key in PKCS8 format, fill in the following | |
35 | * header fields: | |
36 | * | |
37 | * CSSM_KEYBLOB_FORMAT Format | |
38 | * CSSM_ALGORITHMS AlgorithmId | |
39 | * uint32 LogicalKeySizeInBits | |
40 | */ | |
41 | void AppleCSPSession::pkcs8InferKeyHeader( | |
42 | CssmKey &key) | |
43 | { | |
44 | /* | |
45 | * Incoming key blob is a PrivateKeyInfo. Take it apart | |
46 | * to get its algorithm info, from which we infer other | |
47 | * fields. | |
48 | */ | |
49 | NSS_PrivateKeyInfo privKeyInfo; | |
50 | SecNssCoder coder; | |
51 | CSSM_DATA &keyData = key.KeyData; | |
52 | ||
53 | memset(&privKeyInfo, 0, sizeof(privKeyInfo)); | |
54 | if(coder.decodeItem(keyData, kSecAsn1PrivateKeyInfoTemplate, | |
55 | &privKeyInfo)) { | |
56 | errorLog0("pkcs8InferKeyHeader decode error\n"); | |
57 | CssmError::throwMe(CSSMERR_CSP_INVALID_KEY); | |
58 | } | |
59 | ||
60 | CSSM_KEYHEADER &hdr = key.KeyHeader; | |
61 | if(!cssmOidToAlg(&privKeyInfo.algorithm.algorithm, | |
62 | &hdr.AlgorithmId)) { | |
63 | errorLog0("pkcs8InferKeyHeader unknown algorithm\n"); | |
64 | CssmError::throwMe(CSSMERR_CSP_INVALID_ALGORITHM); | |
65 | } | |
66 | ||
67 | switch(hdr.AlgorithmId) { | |
68 | case CSSM_ALGID_RSA: | |
69 | case CSSM_ALGID_ECDSA: | |
70 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; | |
71 | break; | |
72 | case CSSM_ALGID_DSA: | |
73 | /* | |
74 | * Try openssl style first, though our default when | |
75 | * wrapping is FIPS186 | |
76 | */ | |
77 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; | |
78 | break; | |
79 | default: | |
80 | /* punt */ | |
81 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; | |
82 | break; | |
83 | } | |
84 | ||
85 | /* | |
86 | * Find someone who knows about this key and ask them the | |
87 | * key size. infoProvider() throws if no provider found. | |
88 | */ | |
89 | CSSM_KEY_SIZE keySize; | |
90 | try { | |
91 | auto_ptr<CSPKeyInfoProvider> provider(infoProvider(key)); | |
92 | provider->QueryKeySizeInBits(keySize); | |
93 | } | |
94 | catch(const CssmError &cerror) { | |
95 | /* | |
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. | |
101 | */ | |
102 | if((cerror.error == CSSMERR_CSP_INVALID_KEY) && | |
103 | (hdr.AlgorithmId == CSSM_ALGID_DSA)) { | |
104 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_FIPS186; | |
105 | try { | |
106 | auto_ptr<CSPKeyInfoProvider> provider(infoProvider(key)); | |
107 | provider->QueryKeySizeInBits(keySize); | |
108 | } | |
109 | catch(...) { | |
110 | /* out of luck */ | |
111 | throw; | |
112 | } | |
113 | } | |
114 | else { | |
115 | /* other error, give up */ | |
116 | throw; | |
117 | } | |
118 | } | |
119 | catch(...) { | |
120 | /* other (non-CSSM) error, give up */ | |
121 | throw; | |
122 | } | |
123 | hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; | |
124 | } | |
125 | ||
126 | /* | |
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 | |
131 | * context attribute. | |
132 | */ | |
133 | CSSM_KEYBLOB_FORMAT pkcs8RawKeyFormat( | |
134 | CSSM_ALGORITHMS keyAlg) | |
135 | { | |
136 | switch(keyAlg) { | |
137 | case CSSM_ALGID_RSA: | |
138 | case CSSM_ALGID_ECDSA: | |
139 | return CSSM_KEYBLOB_RAW_FORMAT_PKCS8; | |
140 | case CSSM_ALGID_DSA: | |
141 | return CSSM_KEYBLOB_RAW_FORMAT_FIPS186; | |
142 | default: | |
143 | /* punt */ | |
144 | return CSSM_KEYBLOB_RAW_FORMAT_NONE; | |
145 | } | |
146 | } | |
147 | ||
148 | /* | |
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 | |
153 | * context attribute. | |
154 | */ | |
155 | CSSM_KEYBLOB_FORMAT opensslRawKeyFormat( | |
156 | CSSM_ALGORITHMS keyAlg) | |
157 | { | |
158 | switch(keyAlg) { | |
159 | case CSSM_ALGID_RSA: | |
160 | return CSSM_KEYBLOB_RAW_FORMAT_PKCS1; | |
161 | case CSSM_ALGID_DSA: | |
162 | return CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; | |
163 | case CSSM_ALGID_ECDSA: | |
164 | return CSSM_KEYBLOB_RAW_FORMAT_PKCS8; | |
165 | default: | |
166 | /* punt */ | |
167 | return CSSM_KEYBLOB_RAW_FORMAT_NONE; | |
168 | } | |
169 | } | |
170 | ||
171 | /* | |
172 | * Given a key in some kind of openssl format (just subsequent to decryption | |
173 | * during an unwrap), fill in the following header fields: | |
174 | * | |
175 | * CSSM_KEYBLOB_FORMAT Format | |
176 | * uint32 LogicalKeySizeInBits | |
177 | */ | |
178 | void AppleCSPSession::opensslInferKeyHeader( | |
179 | CssmKey &key) | |
180 | { | |
181 | CSSM_KEYHEADER &hdr = key.KeyHeader; | |
182 | switch(hdr.AlgorithmId) { | |
183 | case CSSM_ALGID_RSA: | |
184 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS1; | |
185 | break; | |
186 | case CSSM_ALGID_DSA: | |
187 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_OPENSSL; | |
188 | break; | |
189 | case CSSM_ALGID_ECDSA: | |
190 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_PKCS8; | |
191 | break; | |
192 | default: | |
193 | /* punt */ | |
194 | hdr.Format = CSSM_KEYBLOB_RAW_FORMAT_NONE; | |
195 | return; | |
196 | } | |
197 | ||
198 | /* now figure out the key size by finding a provider for this key */ | |
199 | CSSM_KEY_SIZE keySize; | |
200 | try { | |
201 | auto_ptr<CSPKeyInfoProvider> provider(infoProvider(key)); | |
202 | provider->QueryKeySizeInBits(keySize); | |
203 | } | |
204 | catch(...) { | |
205 | /* no recovery possible */ | |
206 | throw; | |
207 | } | |
208 | hdr.LogicalKeySizeInBits = keySize.LogicalKeySizeInBits; | |
209 | return; | |
210 | } | |
211 |